source: rtems/cpukit/sapi/src/ioregisterdriver.c @ a211a732

4.115
Last change on this file since a211a732 was 04cf2c5, checked in by Daniel Hellstrom <daniel@…>, on 11/24/11 at 15:54:28

IO_MANAGER: early dynamic driver registration

Adds the possibility to register drivers before the IO Manager has
completed the initialization. Sometimes the BSP may want to register
a driver dynamically early in the boot process.

  • Property mode set to 100644
File size: 2.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ClassicIO
5 *
6 * @brief Classic Input/Output Manager implementation.
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2009.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  Copyright (c) 2009 embedded brains GmbH.
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <rtems/io.h>
25#include <rtems/rtems/intr.h>
26#include <rtems/score/threaddispatch.h>
27
28extern int _IO_Manager_drivers_inititalized;
29
30static inline bool rtems_io_is_empty_table(
31  const rtems_driver_address_table *table
32)
33{
34  return table->initialization_entry == NULL && table->open_entry == NULL;
35}
36
37static rtems_status_code rtems_io_obtain_major_number(
38  rtems_device_major_number *major
39)
40{
41  rtems_device_major_number n = _IO_Number_of_drivers;
42  rtems_device_major_number m = 0;
43
44  /* major is error checked by caller */
45
46  for ( m = 0; m < n; ++m ) {
47    rtems_driver_address_table *const table = _IO_Driver_address_table + m;
48
49    if ( rtems_io_is_empty_table( table ) )
50      break;
51  }
52
53  /* Assigns invalid value in case of failure */
54  *major = m;
55
56  if ( m != n )
57    return RTEMS_SUCCESSFUL;
58
59  return RTEMS_TOO_MANY;
60}
61
62rtems_status_code rtems_io_register_driver(
63  rtems_device_major_number         major,
64  const rtems_driver_address_table *driver_table,
65  rtems_device_major_number        *registered_major
66)
67{
68  rtems_device_major_number major_limit = _IO_Number_of_drivers;
69
70  if ( rtems_interrupt_is_in_progress() )
71    return RTEMS_CALLED_FROM_ISR;
72
73  if ( registered_major == NULL )
74    return RTEMS_INVALID_ADDRESS;
75
76  /* Set it to an invalid value */
77  *registered_major = major_limit;
78
79  if ( driver_table == NULL )
80    return RTEMS_INVALID_ADDRESS;
81
82  if ( rtems_io_is_empty_table( driver_table ) )
83    return RTEMS_INVALID_ADDRESS;
84
85  if ( major >= major_limit )
86    return RTEMS_INVALID_NUMBER;
87
88  _Thread_Disable_dispatch();
89
90  if ( major == 0 ) {
91    rtems_status_code sc = rtems_io_obtain_major_number( registered_major );
92
93    if ( sc != RTEMS_SUCCESSFUL ) {
94      _Thread_Enable_dispatch();
95      return sc;
96    }
97    major = *registered_major;
98  } else {
99    rtems_driver_address_table *const table = _IO_Driver_address_table + major;
100
101    if ( !rtems_io_is_empty_table( table ) ) {
102      _Thread_Enable_dispatch();
103      return RTEMS_RESOURCE_IN_USE;
104    }
105
106    *registered_major = major;
107  }
108
109  _IO_Driver_address_table [major] = *driver_table;
110
111  _Thread_Enable_dispatch();
112
113  if ( _IO_Manager_drivers_inititalized ) {
114    /* Other drivers have already been initialized, we initialize
115     * the driver directly.
116     */
117    return rtems_io_initialize( major, 0, NULL );
118  } else {
119    /* The driver will be initialized together with all other drivers
120     * in a later stage by _IO_Initialize_all_drivers().
121     */
122    return RTEMS_SUCCESSFUL;
123  }
124}
Note: See TracBrowser for help on using the repository browser.