Changeset d2ff24c2 in rtems


Ignore:
Timestamp:
Nov 21, 2007, 6:20:49 AM (12 years ago)
Author:
Till Straumann <strauman@…>
Branches:
4.10, 4.11, 4.9, master
Children:
d371a97
Parents:
381a2f18
Message:

2007-11-17 Till Straumann <strauman@…>

  • libi2c/libi2c.c, libi2c/libi2c.h, libi2c/README_libi2c: Added checks so that use of 'stdio' is avoided (falling back to 'printk') before the system is up. Publish driver entry points so that the libi2c driver could be added to the applications 'device driver table'. This is not fully implemented yet, though, since in addition to initializing libi2c the low-level i2c bus drivers as well as high-level i2c device drivers need to be registered with the library. Updated README_libi2c accordingly.
Location:
cpukit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    r381a2f18 rd2ff24c2  
     12007-11-17      Till Straumann <strauman@slac.stanford.edu>
     2
     3        * libi2c/libi2c.c, libi2c/libi2c.h, libi2c/README_libi2c:
     4        Added checks so that use of 'stdio' is avoided (falling
     5        back to 'printk') before the system is up.
     6        Publish driver entry points so that the libi2c driver could
     7        be added to the applications 'device driver table'.
     8        This is not fully implemented yet, though, since in addition to
     9        initializing libi2c the low-level i2c bus drivers as well
     10        as high-level i2c device drivers need to be registered
     11        with the library.
     12        Updated README_libi2c accordingly.
     13
    1142007-11-17      Till Straumann <strauman@slac.stanford.edu>
    215
  • cpukit/libi2c/README_libi2c

    r381a2f18 rd2ff24c2  
    109109
    110110Typically the BSP startup code will perform this initialization.
     111
     112A proper place for initializing the i2c layer and populating it
     113with busses and device drivers (see 'Bus Registration' and
     114'Device/Driver Registration' below) is the 'predriver_hook'
     115where most facilities (such as malloc, libio) are already
     116available. Note, however, that 'stdio' is not yet functional
     117at this point and all i2c bus and device drivers should carefully
     118avoid using stdio so that other drivers which may build on top
     119of i2c devices may be initialized properly (this may happen
     120just after 'predriver_hook' when stdio is still not available).
     121E.g., drivers listed in the configuration table are initialized
     122during this step.
     123
     124Note that while 'libi2c' could be initialized from the rtems
     125configuration table like other drivers there is no easy
     126way of populating the i2c framework with bus- and device-
     127drivers at this point (unless a special 'i2c' configuration
     128table describing the bus layout is implemented in the future).
     129
     130For the time being, we must rely on the BSP (predriver_hook)
     131to initialize the i2c system if it is used by other drivers
     132(e.g., the RTC driver may have to use a i2c device).
    111133
    112134===================
  • cpukit/libi2c/libi2c.c

    r381a2f18 rd2ff24c2  
    6464#include <rtems.h>
    6565#include <rtems/error.h>
     66#include <rtems/bspIo.h>
    6667#include <rtems/libio.h>
    6768
     
    104105rtems_device_major_number rtems_libi2c_major;
    105106
     107static boolean            is_initialized = FALSE;
     108
    106109static struct i2cbus
    107110{
     
    133136         |RTEMS_LOCAL )
    134137
    135 static rtems_id
    136 mutexCreate (rtems_name nm)
     138/* During early stages of life, stdio is not available */
     139
     140static void
     141safe_printf (const char *fmt, ...)
     142{
     143va_list ap;
     144
     145        va_start(ap, fmt);
     146        if ( _System_state_Is_up( _System_state_Get() ) )
     147                vfprintf( stderr, fmt, ap );
     148        else
     149                vprintk( fmt, ap );
     150        va_end(ap);
     151}
     152
     153static rtems_status_code
     154mutexCreate (rtems_name nm, rtems_id *pm)
    137155{
    138156  rtems_status_code sc;
    139   rtems_id rval;
     157
    140158  if (RTEMS_SUCCESSFUL !=
    141       (sc = rtems_semaphore_create (nm, 1, MUTEX_ATTS, 0, &rval))) {
    142     rtems_error (sc, DRVNM " unable to create mutex\n");
    143     return 0;
    144   }
    145   return rval;
     159      (sc = rtems_semaphore_create (nm, 1, MUTEX_ATTS, 0, pm))) {
     160        if ( _System_state_Is_up( _System_state_Get() ) )
     161        rtems_error (sc, DRVNM " unable to create mutex\n");
     162        else
     163                printk (DRVNM " unable to crate mutex (status code %i)\n", sc);
     164  }
     165  return sc;
    146166}
    147167
     
    156176lock_bus (int busno)
    157177{
    158   struct i2cbus *bus = &busses[busno];
     178rtems_status_code sc;
     179struct i2cbus *bus = &busses[busno];
     180
    159181  LIBLOCK ();
    160182  if (!bus->waiting) {
     183        rtems_id m;
    161184    /* nobody is holding the bus mutex - it's not there. Create it on the fly */
    162     if (!
    163         (bus->mutex =
    164          mutexCreate (rtems_build_name ('i', '2', 'c', '0' + busno)))) {
     185    sc = mutexCreate (rtems_build_name ('i', '2', 'c', '0' + busno), &m);
     186    if ( RTEMS_SUCCESSFUL != sc ) {
    165187      LIBUNLOCK ();
    166188      rtems_panic (DRVNM " unable to create bus lock");
    167     }
     189    } else {
     190          bus->mutex = m;
     191        }
    168192  }
    169193  /* count number of people waiting on this bus; only the last one deletes the mutex */
     
    187211
    188212/* Note that 'arg' is always passed in as NULL */
    189 static rtems_status_code
    190 i2c_init (rtems_device_major_number major, rtems_device_minor_number minor,
     213rtems_status_code
     214rtems_i2c_init (rtems_device_major_number major, rtems_device_minor_number minor,
    191215          void *arg)
    192216{
    193217  rtems_status_code rval;
     218  /* No busses or drivers can be registered at this point;
     219   * avoid the macro aborting with an error
    194220  DECL_CHECKED_DRV (drv, busno, minor)
    195 
    196     if (0 == drv) {
    197     rval = 0;
     221   */
     222
     223  rval = mutexCreate (rtems_build_name ('l', 'I', '2', 'C'), &libmutex);
     224
     225  if ( RTEMS_SUCCESSFUL == rval ) {
     226        is_initialized     = TRUE;
     227        rtems_libi2c_major = major;
    198228  } else {
    199     /* this is probably never called */
    200     DISPATCH (rval, initialization_entry, RTEMS_SUCCESSFUL);
    201   }
    202   return rval;
    203 }
    204 
    205 static rtems_status_code
    206 i2c_open (rtems_device_major_number major, rtems_device_minor_number minor,
     229        libmutex = 0;
     230  }
     231  return rval;
     232}
     233
     234rtems_status_code
     235rtems_i2c_open (rtems_device_major_number major, rtems_device_minor_number minor,
    207236          void *arg)
    208237{
     
    218247}
    219248
    220 static rtems_status_code
    221 i2c_close (rtems_device_major_number major, rtems_device_minor_number minor,
     249rtems_status_code
     250rtems_i2c_close (rtems_device_major_number major, rtems_device_minor_number minor,
    222251           void *arg)
    223252{
     
    233262}
    234263
    235 static rtems_status_code
    236 i2c_read (rtems_device_major_number major, rtems_device_minor_number minor,
     264rtems_status_code
     265rtems_i2c_read (rtems_device_major_number major, rtems_device_minor_number minor,
    237266          void *arg)
    238267{
     
    263292}
    264293
    265 static rtems_status_code
    266 i2c_write (rtems_device_major_number major, rtems_device_minor_number minor,
     294rtems_status_code
     295rtems_i2c_write (rtems_device_major_number major, rtems_device_minor_number minor,
    267296           void *arg)
    268297{
     
    293322}
    294323
    295 static rtems_status_code
    296 i2c_ioctl (rtems_device_major_number major, rtems_device_minor_number minor,
     324rtems_status_code
     325rtems_i2c_ioctl (rtems_device_major_number major, rtems_device_minor_number minor,
    297326           void *arg)
    298327{
     
    310339
    311340/* Our ops just dispatch to the registered drivers */
    312 static rtems_driver_address_table libi2c_io_ops = {
    313   initialization_entry:  i2c_init,
    314   open_entry:            i2c_open,
    315   close_entry:           i2c_close,
    316   read_entry:            i2c_read,
    317   write_entry:           i2c_write,
    318   control_entry:         i2c_ioctl,
     341rtems_driver_address_table rtems_libi2c_io_ops = {
     342  initialization_entry:  rtems_i2c_init,
     343  open_entry:            rtems_i2c_open,
     344  close_entry:           rtems_i2c_close,
     345  read_entry:            rtems_i2c_read,
     346  write_entry:           rtems_i2c_write,
     347  control_entry:         rtems_i2c_ioctl,
    319348};
    320 
    321349
    322350int
     
    324352{
    325353  rtems_status_code sc;
    326   static boolean is_initialized = FALSE;
    327354
    328355  if (is_initialized) {
     
    333360  }
    334361 
    335   if (!(libmutex = mutexCreate (rtems_build_name ('l', 'I', '2', 'C'))))
    336     return -1;
    337 
    338   sc = rtems_io_register_driver (0, &libi2c_io_ops, &rtems_libi2c_major);
     362  /* rtems_io_register_driver does NOT currently check nor report back
     363   * the return code of the 'init' operation, so we cannot
     364   * rely on return code since it may seem OK even if the driver 'init;
     365   * op failed.
     366   * Let 'init' handle 'is_initialized'...
     367   */
     368  sc = rtems_io_register_driver (0, &rtems_libi2c_io_ops, &rtems_libi2c_major);
    339369  if (RTEMS_SUCCESSFUL != sc) {
    340     fprintf (stderr,
     370    safe_printf(
    341371             DRVNM " Claiming driver slot failed (rtems status code %i)\n",
    342372             sc);
    343     rtems_semaphore_delete (libmutex);
     373        if ( libmutex )
     374        rtems_semaphore_delete (libmutex);
    344375    libmutex = 0;
     376        is_initialized = FALSE;
    345377    return -1;
    346378  }
    347   is_initialized = TRUE;
    348379
    349380  return 0;
     
    364395  /* check */
    365396  if ('/' != *nmcpy) {
    366     fprintf (stderr,
    367              "Bad name; must be an absolute path starting with '/'\n");
     397    safe_printf ( DRVNM "Bad name; must be an absolute path starting with '/'\n");
    368398    return -RTEMS_INVALID_NAME;
    369399  }
    370400  /* file must not exist */
    371401  if (!stat (nmcpy, &sbuf)) {
    372     fprintf (stderr, "Bad name; file exists already\n");
     402    safe_printf ( DRVNM "Bad name; file exists already\n");
    373403    return -RTEMS_INVALID_NAME;
    374404  }
     
    381411  *chpt = tmp;
    382412  if (i) {
    383     fprintf (stderr, "Get %s status failed: %s\n",
    384              nmcpy,strerror(errno));
     413    safe_printf ( DRVNM "Get %s status failed: %s\n",
     414             nmcpy, strerror(errno));
    385415    return -RTEMS_INVALID_NAME;
    386416  }
     
    389419
    390420  if (!libmutex) {
    391     fprintf (stderr, DRVNM " library not initialized\n");
     421    safe_printf ( DRVNM " library not initialized\n");
    392422    return -RTEMS_NOT_DEFINED;
    393423  }
    394424
    395425  if (bus->size < sizeof (*bus)) {
    396     fprintf (stderr, DRVNM " bus-ops size too small -- misconfiguration?\n");
     426    safe_printf ( DRVNM " bus-ops size too small -- misconfiguration?\n");
    397427    return -RTEMS_NOT_CONFIGURED;
    398428  }
     
    654684
    655685  if (!libmutex) {
    656     fprintf (stderr, DRVNM " library not initialized\n");
     686    safe_printf ( DRVNM " library not initialized\n");
    657687    return -RTEMS_NOT_DEFINED;
    658688  }
    659689
    660690  if (name && strchr (name, '/')) {
    661     fprintf (stderr, "Invalid name: '%s' -- must not contain '/'\n", name);
     691    safe_printf ( DRVNM "Invalid name: '%s' -- must not contain '/'\n", name);
    662692    return -RTEMS_INVALID_NAME;
    663693  }
     
    669699
    670700  if (drvtbl->size < sizeof (*drvtbl)) {
    671     fprintf (stderr, DRVNM " drv-ops size too small -- misconfiguration?\n");
     701    safe_printf ( DRVNM " drv-ops size too small -- misconfiguration?\n");
    672702    return -RTEMS_NOT_CONFIGURED;
    673703  }
     
    699729        /* note that 'umask' is applied to 'mode' */
    700730        if (mknod (str, mode, dev)) {
    701           fprintf (stderr,
     731          safe_printf( DRVNM
    702732                   "Creating device node failed: %s; you can try to do it manually...\n",
    703733                   strerror (errno));
  • cpukit/libi2c/libi2c.h

    r381a2f18 rd2ff24c2  
    6060/* Initialize the libary - may fail if no semaphore or no driver slot is available */
    6161int rtems_libi2c_initialize ();
     62
     63/* Alternatively to rtems_libi2c_initialize() the library can also be
     64 * initialized by means of a traditional driver table entry containing
     65 * the following entry points:
     66 */
     67rtems_status_code
     68rtems_i2c_init (
     69        rtems_device_major_number major,
     70        rtems_device_minor_number minor,
     71    void *arg);
     72
     73rtems_status_code
     74rtems_i2c_open (
     75        rtems_device_major_number major,
     76        rtems_device_minor_number minor,
     77    void *arg);
     78
     79rtems_status_code
     80rtems_i2c_close (
     81        rtems_device_major_number major,
     82        rtems_device_minor_number minor,
     83    void *arg);
     84
     85rtems_status_code
     86rtems_i2c_read (
     87        rtems_device_major_number major,
     88        rtems_device_minor_number minor,
     89    void *arg);
     90
     91rtems_status_code
     92rtems_i2c_write (
     93        rtems_device_major_number major,
     94        rtems_device_minor_number minor,
     95    void *arg);
     96
     97rtems_status_code
     98rtems_i2c_ioctl (
     99        rtems_device_major_number major,
     100        rtems_device_minor_number minor,
     101    void *arg);
     102
     103extern rtems_driver_address_table rtems_libi2c_io_ops;
     104
     105/* Unfortunately, if you want to add this driver to
     106 * a RTEMS configuration table then you need all the
     107 * members explicitly :-( (Device_driver_table should
     108 * hold pointers to rtems_driver_address_tables rather
     109 * than full structs).
     110 *
     111 * The difficulty is that adding this driver to the
     112 * configuration table is not enough; you still need
     113 * to populate the framework with low-level bus-driver(s)
     114 * and high-level drivers and/or device-files...
     115 *
     116 * Currently the preferred way is having the BSP
     117 * call 'rtems_libi2c_initialize' followed by
     118 * 'rtems_libi2c_register_bus' and
     119 * 'rtems_libi2c_register_drv' and/or
     120 * 'mknod' (for 'raw' device nodes)
     121 * from the 'pretasking_hook'.
     122 */
     123#define RTEMS_LIBI2C_DRIVER_TABLE_ENTRY   \
     124{                                         \
     125  initialization_entry:  rtems_i2c_init,  \
     126  open_entry:            rtems_i2c_open,  \
     127  close_entry:           rtems_i2c_close, \
     128  read_entry:            rtems_i2c_read,  \
     129  write_entry:           rtems_i2c_write, \
     130  control_entry:         rtems_i2c_ioctl, \
     131}
    62132
    63133/* Bus Driver API
Note: See TracChangeset for help on using the changeset viewer.