summaryrefslogtreecommitdiffstats
path: root/cpukit/sapi
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-10-05 15:00:53 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-10-05 15:00:53 +0000
commit456a77680c32555167bcc10a1b2d1697bdf341eb (patch)
tree7902ee905094ccd98b9c4683b9ad34777065b7ce /cpukit/sapi
parent2009-10-05 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-456a77680c32555167bcc10a1b2d1697bdf341eb.tar.bz2
2009-10-04 Sebastian Huber <Sebastian.Huber@embedded-brains.de>
* sapi/include/rtems/io.h, sapi/src/ioregisterdriver.c: Documenation. rtems_io_lookup_name() is now deprecated. Added rtems_io_driver_io_error(). rtems_io_register_driver() is now thread-safe.
Diffstat (limited to 'cpukit/sapi')
-rw-r--r--cpukit/sapi/include/rtems/io.h252
-rw-r--r--cpukit/sapi/src/ioregisterdriver.c155
2 files changed, 194 insertions, 213 deletions
diff --git a/cpukit/sapi/include/rtems/io.h b/cpukit/sapi/include/rtems/io.h
index fc03ec74fd..ba867c46f3 100644
--- a/cpukit/sapi/include/rtems/io.h
+++ b/cpukit/sapi/include/rtems/io.h
@@ -1,19 +1,9 @@
/**
- * @file rtems/io.h
+ * @file
*
- * This include file contains all the constants and structures associated
- * with the Input/Output Manager. This manager provides a well defined
- * mechanism for accessing device drivers and a structured methodology for
- * organizing device drivers.
+ * @ingroup ClassicIO
*
- * Directives provided are:
- *
- * + initialize a device driver
- * + open a device driver
- * + close a device driver
- * + read from a device driver
- * + write to a device driver
- * + special device services
+ * @brief Classic Input/Output Manager API.
*/
/*
@@ -40,136 +30,105 @@
extern "C" {
#endif
-/*
+/**
+ * @defgroup ClassicIO Input/Output
*
- * The following defines the types for:
+ * @ingroup ClassicRTEMS
*
- * + major and minor numbers
- * + the return type of a device driver entry
- * + a pointer to a device driver entry
- * + an entry in the the Device Driver Address Table. Each entry in this
- * table corresponds to an application provided device driver and
- * defines the entry points for that device driver.
+ * @{
*/
-typedef uint32_t rtems_device_major_number;
-typedef uint32_t rtems_device_minor_number;
+typedef uint32_t rtems_device_major_number;
+
+typedef uint32_t rtems_device_minor_number;
typedef rtems_status_code rtems_device_driver;
-typedef rtems_device_driver ( *rtems_device_driver_entry )(
- rtems_device_major_number,
- rtems_device_minor_number,
- void *
- );
+typedef rtems_device_driver (*rtems_device_driver_entry)(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
typedef struct {
- rtems_device_driver_entry initialization_entry; /* initialization procedure */
- rtems_device_driver_entry open_entry; /* open request procedure */
- rtems_device_driver_entry close_entry; /* close request procedure */
- rtems_device_driver_entry read_entry; /* read request procedure */
- rtems_device_driver_entry write_entry; /* write request procedure */
- rtems_device_driver_entry control_entry; /* special functions procedure */
-} rtems_driver_address_table;
+ rtems_device_driver_entry initialization_entry;
+ rtems_device_driver_entry open_entry;
+ rtems_device_driver_entry close_entry;
+ rtems_device_driver_entry read_entry;
+ rtems_device_driver_entry write_entry;
+ rtems_device_driver_entry control_entry;
+} rtems_driver_address_table;
-/*
- * Table for the io device names
- */
-
-typedef struct {
- char *device_name;
- size_t device_name_length;
- rtems_device_major_number major;
- rtems_device_minor_number minor;
-} rtems_driver_name_t;
-
-/*
- * This is the table of device names.
- */
-
-/*
- * The following declare the data required to manage the Driver
- * Address Table and Device Name Table.
+/**
+ * @name Device Driver Maintainance
+ *
+ * @{
*/
-SAPI_IO_EXTERN uint32_t _IO_Number_of_drivers;
-SAPI_IO_EXTERN rtems_driver_address_table *_IO_Driver_address_table;
-
-/*
- * _IO_Manager_initialization
- *
- * DESCRIPTION:
+/**
+ * @brief Returns @c RTEMS_IO_ERROR.
*
- * This routine performs the initialization necessary for this manager.
+ * @retval RTEMS_IO_ERROR Only this one.
*/
+rtems_status_code rtems_io_driver_io_error(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
-void _IO_Manager_initialization(void);
-
-/*
- * rtems_io_register_driver
+/**
+ * @brief Registers and initializes the device with the device driver table
+ * @a driver_table and major number @a major.
*
- * DESCRIPTION:
+ * If the major number equals zero a major number will be obtained. The major
+ * number of the registered driver will be returned in @a registered_major.
*
- * Register a driver into the device driver table.
+ * After a successful registration rtems_io_initialize() will be called to
+ * initialize the device.
*
+ * @retval RTEMS_SUCCESSFUL Device successfully registered and initialized.
+ * @retval RTEMS_INVALID_ADDRESS Pointer to driver table or to registered
+ * major number are invalid. Device driver table is empty.
+ * @retval RTEMS_INVALID_NUMBER Invalid major number.
+ * @retval RTEMS_TOO_MANY No major number available.
+ * @retval RTEMS_RESOURCE_IN_USE Major number in use.
+ * @retval * Status code depends on rtems_io_initialize().
*/
-
rtems_status_code rtems_io_register_driver(
- rtems_device_major_number major,
- const rtems_driver_address_table *driver_table,
- rtems_device_major_number *registered_major
+ rtems_device_major_number major,
+ const rtems_driver_address_table *driver_table,
+ rtems_device_major_number *registered_major
);
-/*
- * rtems_io_unregister_driver
- *
- * DESCRIPTION:
- *
- * Unregister a driver from the device driver table.
+/**
+ * @brief Unregisters the device driver with number @a major.
*
+ * @retval RTEMS_SUCCESSFUL Device driver successfully unregistered.
+ * @retval RTEMS_UNSATISFIED Invalid major number.
*/
-
rtems_status_code rtems_io_unregister_driver(
- rtems_device_major_number major
+ rtems_device_major_number major
);
-/*
- * rtems_io_register_name
- *
- * DESCRIPTION:
- *
- * Associate a name with a driver.
+/**
+ * @brief Registers the name @a device_name in the file system for the device
+ * with number tuple @a major and @a minor.
*
+ * @retval RTEMS_SUCCESSFUL Name successfully registered.
+ * @retval RTEMS_TOO_MANY Name already in use or other errors.
*/
-
rtems_status_code rtems_io_register_name(
- const char *device_name,
- rtems_device_major_number major,
- rtems_device_minor_number minor
-);
-
-
-/*
- * rtems_io_lookup_name
- *
- * DESCRIPTION:
- *
- * Find what driver "owns" this name
- */
-
-rtems_status_code rtems_io_lookup_name(
- const char *name,
- rtems_driver_name_t *device_info
+ const char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
);
+/** @} */
-/*
- * rtems_io_initialize
- *
- * DESCRIPTION:
+/**
+ * @name Device Driver Invocation
*
- * This routine implements the rtems_io_initialize directive. It is invoked
- * to initialize a device driver or an individual device.
+ * @{
*/
rtems_status_code rtems_io_initialize(
@@ -178,89 +137,60 @@ rtems_status_code rtems_io_initialize(
void *argument
);
-/*
- * rtems_io_open
- *
- * DESCRIPTION:
- *
- * This routine implements the rtems_io_open directive. It is invoked
- * to open a device.
- */
-
rtems_status_code rtems_io_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *argument
);
-/*
- * rtems_io_close
- *
- * DESCRIPTION:
- *
- * This routine implements the rtems_io_close directive. It is invoked
- * to close a device.
- */
-
rtems_status_code rtems_io_close(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *argument
);
-/*
- * rtems_io_read
- *
- * DESCRIPTION:
- *
- * This routine implements the rtems_io_read directive. It is invoked
- * to read from a device.
- */
-
rtems_status_code rtems_io_read(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *argument
);
-/*
- * rtems_io_write
- *
- * DESCRIPTION:
- *
- * This routine implements the rtems_io_write directive. It is invoked
- * to write to a device.
- */
-
rtems_status_code rtems_io_write(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *argument
);
-/*
- * rtems_io_control
- *
- * DESCRIPTION:
- *
- * This routine implements the rtems_io_control directive. It is invoked
- * to perform a device specific operation on a device.
- */
-
rtems_status_code rtems_io_control(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *argument
);
-/*
- * _IO_Initialize_all_drivers
- *
- * DESCRIPTION:
- *
- * This routine initializes all of the device drivers configured
- * in the Device Driver Address Table.
+/** @} */
+
+/** @} */
+
+typedef struct {
+ char *device_name;
+ size_t device_name_length;
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} rtems_driver_name_t;
+
+/**
+ * @deprecated Use stat() instead.
*/
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t *device_info
+) RTEMS_COMPILER_DEPRECATED_ATTRIBUTE;
+
+SAPI_IO_EXTERN uint32_t _IO_Number_of_drivers;
+
+SAPI_IO_EXTERN rtems_driver_address_table *_IO_Driver_address_table;
+
+void _IO_Manager_initialization( void );
void _IO_Initialize_all_drivers( void );
diff --git a/cpukit/sapi/src/ioregisterdriver.c b/cpukit/sapi/src/ioregisterdriver.c
index 9036452310..61040f3e8f 100644
--- a/cpukit/sapi/src/ioregisterdriver.c
+++ b/cpukit/sapi/src/ioregisterdriver.c
@@ -1,9 +1,17 @@
-/*
- * Input/Output Manager - Dynamically Register Device Driver
+/**
+ * @file
+ *
+ * @ingroup ClassicIO
*
+ * @brief Classic Input/Output Manager implementation.
+ */
+
+/*
* COPYRIGHT (c) 1989-2009.
* On-Line Applications Research Corporation (OAR).
*
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -17,76 +25,119 @@
#include <rtems/system.h>
#include <rtems/io.h>
+#include <rtems/rtems/intr.h>
-/*
- * rtems_io_register_driver
- *
- * Register a driver into the device driver table.
- *
- * Input Paramters:
- * major - device major number (0 means allocate
- * a number)
- * driver_table - driver callout function table
- * registered_major - the major number which is registered
- *
- * Output Parameters:
- * RTEMS_SUCCESSFUL - if successful
- * error code - if unsuccessful
- */
+rtems_status_code rtems_io_driver_io_error(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return RTEMS_IO_ERROR;
+}
+
+static inline bool rtems_io_is_empty_table(
+ const rtems_driver_address_table *table
+)
+{
+ return table->initialization_entry == NULL && table->open_entry == NULL;
+}
+
+static inline void rtems_io_occupy_table(
+ rtems_driver_address_table *table
+)
+{
+ table->open_entry = rtems_io_driver_io_error;
+}
+
+static rtems_status_code rtems_io_obtain_major_number(
+ rtems_device_major_number *major
+)
+{
+ rtems_device_major_number n = _IO_Number_of_drivers;
+ rtems_device_major_number m = 0;
+
+ if ( major == NULL ) {
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ for ( m = 0; m < n; ++m ) {
+ rtems_driver_address_table *const table = _IO_Driver_address_table + m;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level );
+ if ( rtems_io_is_empty_table( table ) ) {
+ rtems_io_occupy_table( table );
+ rtems_interrupt_enable( level );
+
+ break;
+ }
+ rtems_interrupt_enable( level );
+ }
+
+ /* Assigns invalid value in case of failure */
+ *major = m;
+
+ if ( m != n ) {
+ return RTEMS_SUCCESSFUL;
+ } else {
+ return RTEMS_TOO_MANY;
+ }
+}
rtems_status_code rtems_io_register_driver(
- rtems_device_major_number major,
+ rtems_device_major_number major,
const rtems_driver_address_table *driver_table,
- rtems_device_major_number *registered_major
+ rtems_device_major_number *registered_major
)
{
+ rtems_device_major_number major_limit = _IO_Number_of_drivers;
- /*
- * Validate the pointer data and contents passed in
- */
- if ( !driver_table )
+ if ( registered_major == NULL ) {
return RTEMS_INVALID_ADDRESS;
+ }
- if ( !registered_major )
- return RTEMS_INVALID_ADDRESS;
+ /* Set it to an invalid value */
+ *registered_major = major_limit;
- if ( !driver_table->initialization_entry && !driver_table->open_entry )
+ if ( driver_table == NULL ) {
return RTEMS_INVALID_ADDRESS;
+ }
- *registered_major = 0;
+ if ( rtems_io_is_empty_table( driver_table ) ) {
+ return RTEMS_INVALID_ADDRESS;
+ }
- /*
- * The requested major number is higher than what is configured.
- */
- if ( major >= _IO_Number_of_drivers )
+ if ( major >= major_limit ) {
return RTEMS_INVALID_NUMBER;
-
- /*
- * Test for initialise/open being present to indicate the driver slot is
- * in use.
- */
+ }
if ( major == 0 ) {
- bool found = false;
- for ( major = _IO_Number_of_drivers - 1 ; major ; major-- ) {
- if ( !_IO_Driver_address_table[major].initialization_entry &&
- !_IO_Driver_address_table[major].open_entry ) {
- found = true;
- break;
- }
- }
+ rtems_status_code sc = rtems_io_obtain_major_number( registered_major );
- if ( !found )
+ if ( sc == RTEMS_SUCCESSFUL ) {
+ major = *registered_major;
+ } else {
return RTEMS_TOO_MANY;
- }
-
- if ( _IO_Driver_address_table[major].initialization_entry ||
- _IO_Driver_address_table[major].open_entry )
- return RTEMS_RESOURCE_IN_USE;
+ }
+ } else {
+ rtems_driver_address_table *const table = _IO_Driver_address_table + major;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level );
+ if ( rtems_io_is_empty_table( table ) ) {
+ rtems_io_occupy_table( table );
+ rtems_interrupt_enable( level );
+ } else {
+ rtems_interrupt_enable( level );
+
+ return RTEMS_RESOURCE_IN_USE;
+ }
+ *registered_major = major;
+ }
- _IO_Driver_address_table[major] = *driver_table;
- *registered_major = major;
+ _IO_Driver_address_table [major] = *driver_table;
return rtems_io_initialize( major, 0, NULL );
}