summaryrefslogtreecommitdiffstats
path: root/cpukit/libi2c/libi2c.c
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2007-11-21 06:20:49 +0000
committerTill Straumann <strauman@slac.stanford.edu>2007-11-21 06:20:49 +0000
commitd2ff24c22d65f24163e9063c78896459384c5627 (patch)
treedfffba11bf10034e1bd9f9a79707b1bc33fb0d48 /cpukit/libi2c/libi2c.c
parent2007-11-20 Till Straumann <strauman@slac.stanford.edu> (diff)
downloadrtems-d2ff24c22d65f24163e9063c78896459384c5627.tar.bz2
2007-11-17 Till Straumann <strauman@slac.stanford.edu>
* 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.
Diffstat (limited to 'cpukit/libi2c/libi2c.c')
-rw-r--r--cpukit/libi2c/libi2c.c140
1 files changed, 85 insertions, 55 deletions
diff --git a/cpukit/libi2c/libi2c.c b/cpukit/libi2c/libi2c.c
index 7069b35527..7adb793e3a 100644
--- a/cpukit/libi2c/libi2c.c
+++ b/cpukit/libi2c/libi2c.c
@@ -63,6 +63,7 @@
#include <rtems.h>
#include <rtems/error.h>
+#include <rtems/bspIo.h>
#include <rtems/libio.h>
#include <rtems/libi2c.h>
@@ -103,6 +104,8 @@
rtems_device_major_number rtems_libi2c_major;
+static boolean is_initialized = FALSE;
+
static struct i2cbus
{
rtems_libi2c_bus_t *bush;
@@ -132,17 +135,34 @@ static rtems_id libmutex = 0;
|RTEMS_NO_PRIORITY_CEILING \
|RTEMS_LOCAL )
-static rtems_id
-mutexCreate (rtems_name nm)
+/* During early stages of life, stdio is not available */
+
+static void
+safe_printf (const char *fmt, ...)
+{
+va_list ap;
+
+ va_start(ap, fmt);
+ if ( _System_state_Is_up( _System_state_Get() ) )
+ vfprintf( stderr, fmt, ap );
+ else
+ vprintk( fmt, ap );
+ va_end(ap);
+}
+
+static rtems_status_code
+mutexCreate (rtems_name nm, rtems_id *pm)
{
rtems_status_code sc;
- rtems_id rval;
+
if (RTEMS_SUCCESSFUL !=
- (sc = rtems_semaphore_create (nm, 1, MUTEX_ATTS, 0, &rval))) {
- rtems_error (sc, DRVNM " unable to create mutex\n");
- return 0;
+ (sc = rtems_semaphore_create (nm, 1, MUTEX_ATTS, 0, pm))) {
+ if ( _System_state_Is_up( _System_state_Get() ) )
+ rtems_error (sc, DRVNM " unable to create mutex\n");
+ else
+ printk (DRVNM " unable to crate mutex (status code %i)\n", sc);
}
- return rval;
+ return sc;
}
/* Lock a bus avoiding to have a mutex, which is mostly
@@ -155,16 +175,20 @@ mutexCreate (rtems_name nm)
static void
lock_bus (int busno)
{
- struct i2cbus *bus = &busses[busno];
+rtems_status_code sc;
+struct i2cbus *bus = &busses[busno];
+
LIBLOCK ();
if (!bus->waiting) {
+ rtems_id m;
/* nobody is holding the bus mutex - it's not there. Create it on the fly */
- if (!
- (bus->mutex =
- mutexCreate (rtems_build_name ('i', '2', 'c', '0' + busno)))) {
+ sc = mutexCreate (rtems_build_name ('i', '2', 'c', '0' + busno), &m);
+ if ( RTEMS_SUCCESSFUL != sc ) {
LIBUNLOCK ();
rtems_panic (DRVNM " unable to create bus lock");
- }
+ } else {
+ bus->mutex = m;
+ }
}
/* count number of people waiting on this bus; only the last one deletes the mutex */
bus->waiting++;
@@ -186,24 +210,29 @@ unlock_bus (int busno)
}
/* Note that 'arg' is always passed in as NULL */
-static rtems_status_code
-i2c_init (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_init (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
rtems_status_code rval;
+ /* No busses or drivers can be registered at this point;
+ * avoid the macro aborting with an error
DECL_CHECKED_DRV (drv, busno, minor)
+ */
- if (0 == drv) {
- rval = 0;
+ rval = mutexCreate (rtems_build_name ('l', 'I', '2', 'C'), &libmutex);
+
+ if ( RTEMS_SUCCESSFUL == rval ) {
+ is_initialized = TRUE;
+ rtems_libi2c_major = major;
} else {
- /* this is probably never called */
- DISPATCH (rval, initialization_entry, RTEMS_SUCCESSFUL);
+ libmutex = 0;
}
return rval;
}
-static rtems_status_code
-i2c_open (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_open (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
rtems_status_code rval;
@@ -217,8 +246,8 @@ i2c_open (rtems_device_major_number major, rtems_device_minor_number minor,
return rval;
}
-static rtems_status_code
-i2c_close (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_close (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
rtems_status_code rval;
@@ -232,8 +261,8 @@ i2c_close (rtems_device_major_number major, rtems_device_minor_number minor,
return rval;
}
-static rtems_status_code
-i2c_read (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_read (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
int rval; /* int so we can check for negative value */
@@ -262,8 +291,8 @@ i2c_read (rtems_device_major_number major, rtems_device_minor_number minor,
return rval;
}
-static rtems_status_code
-i2c_write (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_write (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
int rval; /* int so we can check for negative value */
@@ -292,8 +321,8 @@ i2c_write (rtems_device_major_number major, rtems_device_minor_number minor,
return rval;
}
-static rtems_status_code
-i2c_ioctl (rtems_device_major_number major, rtems_device_minor_number minor,
+rtems_status_code
+rtems_i2c_ioctl (rtems_device_major_number major, rtems_device_minor_number minor,
void *arg)
{
rtems_status_code rval;
@@ -309,21 +338,19 @@ i2c_ioctl (rtems_device_major_number major, rtems_device_minor_number minor,
/* Our ops just dispatch to the registered drivers */
-static rtems_driver_address_table libi2c_io_ops = {
- initialization_entry: i2c_init,
- open_entry: i2c_open,
- close_entry: i2c_close,
- read_entry: i2c_read,
- write_entry: i2c_write,
- control_entry: i2c_ioctl,
+rtems_driver_address_table rtems_libi2c_io_ops = {
+ initialization_entry: rtems_i2c_init,
+ open_entry: rtems_i2c_open,
+ close_entry: rtems_i2c_close,
+ read_entry: rtems_i2c_read,
+ write_entry: rtems_i2c_write,
+ control_entry: rtems_i2c_ioctl,
};
-
int
rtems_libi2c_initialize ()
{
rtems_status_code sc;
- static boolean is_initialized = FALSE;
if (is_initialized) {
/*
@@ -332,19 +359,23 @@ rtems_libi2c_initialize ()
return 0;
}
- if (!(libmutex = mutexCreate (rtems_build_name ('l', 'I', '2', 'C'))))
- return -1;
-
- sc = rtems_io_register_driver (0, &libi2c_io_ops, &rtems_libi2c_major);
+ /* rtems_io_register_driver does NOT currently check nor report back
+ * the return code of the 'init' operation, so we cannot
+ * rely on return code since it may seem OK even if the driver 'init;
+ * op failed.
+ * Let 'init' handle 'is_initialized'...
+ */
+ sc = rtems_io_register_driver (0, &rtems_libi2c_io_ops, &rtems_libi2c_major);
if (RTEMS_SUCCESSFUL != sc) {
- fprintf (stderr,
+ safe_printf(
DRVNM " Claiming driver slot failed (rtems status code %i)\n",
sc);
- rtems_semaphore_delete (libmutex);
+ if ( libmutex )
+ rtems_semaphore_delete (libmutex);
libmutex = 0;
+ is_initialized = FALSE;
return -1;
}
- is_initialized = TRUE;
return 0;
}
@@ -363,13 +394,12 @@ rtems_libi2c_register_bus (char *name, rtems_libi2c_bus_t * bus)
/* check */
if ('/' != *nmcpy) {
- fprintf (stderr,
- "Bad name; must be an absolute path starting with '/'\n");
+ safe_printf ( DRVNM "Bad name; must be an absolute path starting with '/'\n");
return -RTEMS_INVALID_NAME;
}
/* file must not exist */
if (!stat (nmcpy, &sbuf)) {
- fprintf (stderr, "Bad name; file exists already\n");
+ safe_printf ( DRVNM "Bad name; file exists already\n");
return -RTEMS_INVALID_NAME;
}
@@ -380,20 +410,20 @@ rtems_libi2c_register_bus (char *name, rtems_libi2c_bus_t * bus)
i = stat (nmcpy, &sbuf);
*chpt = tmp;
if (i) {
- fprintf (stderr, "Get %s status failed: %s\n",
- nmcpy,strerror(errno));
+ safe_printf ( DRVNM "Get %s status failed: %s\n",
+ nmcpy, strerror(errno));
return -RTEMS_INVALID_NAME;
}
/* should be a directory since name terminates in '/' */
if (!libmutex) {
- fprintf (stderr, DRVNM " library not initialized\n");
+ safe_printf ( DRVNM " library not initialized\n");
return -RTEMS_NOT_DEFINED;
}
if (bus->size < sizeof (*bus)) {
- fprintf (stderr, DRVNM " bus-ops size too small -- misconfiguration?\n");
+ safe_printf ( DRVNM " bus-ops size too small -- misconfiguration?\n");
return -RTEMS_NOT_CONFIGURED;
}
@@ -653,12 +683,12 @@ rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
rtems_device_minor_number minor;
if (!libmutex) {
- fprintf (stderr, DRVNM " library not initialized\n");
+ safe_printf ( DRVNM " library not initialized\n");
return -RTEMS_NOT_DEFINED;
}
if (name && strchr (name, '/')) {
- fprintf (stderr, "Invalid name: '%s' -- must not contain '/'\n", name);
+ safe_printf ( DRVNM "Invalid name: '%s' -- must not contain '/'\n", name);
return -RTEMS_INVALID_NAME;
}
@@ -668,7 +698,7 @@ rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
}
if (drvtbl->size < sizeof (*drvtbl)) {
- fprintf (stderr, DRVNM " drv-ops size too small -- misconfiguration?\n");
+ safe_printf ( DRVNM " drv-ops size too small -- misconfiguration?\n");
return -RTEMS_NOT_CONFIGURED;
}
@@ -698,7 +728,7 @@ rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
/* note that 'umask' is applied to 'mode' */
if (mknod (str, mode, dev)) {
- fprintf (stderr,
+ safe_printf( DRVNM
"Creating device node failed: %s; you can try to do it manually...\n",
strerror (errno));
}