]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/common/v2_0/src/iosys.c
951a218e21ff52040896337b6ad74d11462ce5af
[karo-tx-redboot.git] / packages / io / common / v2_0 / src / iosys.c
1 //==========================================================================
2 //
3 //      io/iosys.c
4 //
5 //      I/O Subsystem + Device Table support
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):   gthomas
44 // Contributors:  gthomas
45 // Date:        1999-02-04
46 // Purpose:     Device I/O Support
47 // Description: 
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/io.h>
54 #include <cyg/io/io.h>
55 #include <cyg/io/devtab.h>
56 #include <cyg/infra/diag.h>
57
58 //extern void cyg_io_init(void) CYGBLD_ATTRIB_CONSTRUCTOR
59 //  CYG_INIT_PRIORITY(CYG_INIT_BEFORE(LIBC));
60
61 // Checks that two strings are "equivalent" device names
62 // 'n1' is a string from the user
63 // 'n2' is a name in a device table entry
64 // 'cyg_io_compare()' will return true IFF
65 //    n1 == n2, for all characters
66 //    n2 ends in '/' and matches n1 up to the terminating '/'
67 // 'ptr' will get a pointer to the residual string.
68 static bool
69 cyg_io_compare(const char *n1, const char *n2, const char **ptr)
70 {
71     while (*n1 && *n2) {
72         if (*n1++ != *n2++) {
73             return false;
74         }
75     }
76     if (*n1) {
77         // See if the devtab name is is a substring
78         if (*(n2-1) == '/') {
79             *ptr = n1;
80             return true;
81         }
82     }
83     if (*n1 || *n2) {
84         return false;
85     }
86     *ptr = n1;
87     return true;
88 }
89
90 //
91 // This function is called during system initialization.  The purpose is
92 // to step through all devices linked into the system, calling their
93 // "init" entry points.  
94 //
95
96 void
97 cyg_io_init(void)
98 {
99     static int _init = false;
100     cyg_devtab_entry_t *t;
101     if (_init) return;
102     for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) {
103 #ifdef CYGDBG_IO_INIT
104         diag_printf("Init device '%s'\n", t->name);
105 #endif
106         if (t->init(t)) {
107             t->status |= CYG_DEVTAB_STATUS_AVAIL;
108         } else {
109             // What to do if device init fails?
110             // Device not [currently] available
111             t->status &= ~CYG_DEVTAB_STATUS_AVAIL;  
112         }
113     }
114     _init = true;
115 }
116
117 //
118 // Look up the devtab entry for a named device and return its handle.
119 // If the device is found and it has a "lookup" function, call that
120 // function to allow the device/driver to perform any necessary
121 // initializations.
122 //
123
124 Cyg_ErrNo
125 cyg_io_lookup(const char *name, cyg_io_handle_t *handle)
126 {
127     union devtab_entry_handle_union {
128         cyg_devtab_entry_t *st;
129         cyg_io_handle_t h;
130     } stunion;
131     cyg_devtab_entry_t *t;
132     Cyg_ErrNo res;
133     const char *name_ptr;
134     for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) {
135         if (cyg_io_compare(name, t->name, &name_ptr)) {
136             // FUTURE: Check 'avail'/'online' here
137             if (t->dep_name) {
138                 res = cyg_io_lookup(t->dep_name, &stunion.h);
139                 if (res != ENOERR) {
140                     return res;
141                 }
142             } else {
143                 stunion.st = NULL;
144             }
145             if (t->lookup) {
146                 // This indirection + the name pointer allows the lookup routine
147                 // to return a different 'devtab' handle.  This will provide for
148                 // 'pluggable' devices, file names, etc.
149                 res = (t->lookup)(&t, stunion.st, name_ptr);
150                 if (res != ENOERR) {
151                     return res;
152                 }
153             }
154             *handle = (cyg_io_handle_t)t;
155             return ENOERR;
156         }
157     }
158     return -ENOENT;  // Not found
159 }
160
161 //
162 // 'write' data to a device.
163 //
164
165 Cyg_ErrNo 
166 cyg_io_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len)
167 {
168     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
169     // Validate request
170     if (!t->handlers->write) {
171         return -EDEVNOSUPP;
172     }
173     // Special check.  If length is zero, this just verifies that the 
174     // 'write' method exists for the given device.
175     if (NULL != len && 0 == *len) {
176         return ENOERR;
177     }
178     return t->handlers->write(handle, buf, len);
179 }
180
181 //
182 // 'read' data from a device.
183 //
184
185 Cyg_ErrNo 
186 cyg_io_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len)
187 {
188     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
189     // Validate request
190     if (!t->handlers->read) {
191         return -EDEVNOSUPP;
192     }
193     // Special check.  If length is zero, this just verifies that the 
194     // 'read' method exists for the given device.
195     if (NULL != len && 0 == *len) {
196         return ENOERR;
197     }
198     return t->handlers->read(handle, buf, len);
199 }
200
201 Cyg_ErrNo 
202 cyg_io_bwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len, cyg_uint32 pos)
203 {
204     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
205     // Validate request
206     if (!t->handlers->bwrite) {
207         return -EDEVNOSUPP;
208     }
209     // Special check.  If length is zero, this just verifies that the 
210     // 'bwrite' method exists for the given device.
211     if (NULL != len && 0 == *len) {
212         return ENOERR;
213     }
214     return t->handlers->bwrite(handle, buf, len, pos);
215 }
216
217 //
218 // 'read' data from a device.
219 //
220
221 Cyg_ErrNo 
222 cyg_io_bread(cyg_io_handle_t handle, void *buf, cyg_uint32 *len, cyg_uint32 pos)
223 {
224     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
225     // Validate request
226     if (!t->handlers->bread) {
227         return -EDEVNOSUPP;
228     }
229     // Special check.  If length is zero, this just verifies that the 
230     // 'bread' method exists for the given device.
231     if (NULL != len && 0 == *len) {
232         return ENOERR;
233     }
234     return t->handlers->bread(handle, buf, len, pos);
235 }
236
237 //
238 // Check device for available input or space for output
239 //
240
241 cyg_bool
242 cyg_io_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
243 {
244     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
245     // Validate request
246     if (!t->handlers->select) {
247         return -EDEVNOSUPP;
248     }
249
250     return t->handlers->select( handle, which, info );
251 }
252
253 //
254 // Get the configuration of a device.
255 //
256
257 Cyg_ErrNo 
258 cyg_io_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len)
259 {
260     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
261     // Validate request
262     if (!t->handlers->get_config) {
263         return -EDEVNOSUPP;
264     }
265     // Special check.  If length is zero, this just verifies that the 
266     // 'get_config' method exists for the given device.
267     if (NULL != len && 0 == *len) {
268         return ENOERR;
269     }
270     return t->handlers->get_config(handle, key, buf, len);
271 }
272
273 //
274 // Change the configuration of a device.
275 //
276
277 Cyg_ErrNo 
278 cyg_io_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len)
279 {
280     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
281     // Validate request
282     if (!t->handlers->set_config) {
283         return -EDEVNOSUPP;
284     }
285     // Special check.  If length is zero, this just verifies that the 
286     // 'set_config' method exists for the given device.
287     if (NULL != len && 0 == *len) {
288         return ENOERR;
289     }
290     return t->handlers->set_config(handle, key, buf, len);
291 }
292
293 /*---------------------------------------------------------------------------*/
294 // Default functions for devio tables
295
296 Cyg_ErrNo cyg_devio_cwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len)
297 {
298     return -EDEVNOSUPP;
299 }
300
301 Cyg_ErrNo cyg_devio_cread(cyg_io_handle_t handle, void *buf, cyg_uint32 *len)
302 {
303     return -EDEVNOSUPP;
304 }
305
306 Cyg_ErrNo cyg_devio_bwrite(cyg_io_handle_t handle, const void *buf,
307                         cyg_uint32 *len, cyg_uint32 pos)
308 {
309     return -EDEVNOSUPP;
310 }
311
312 Cyg_ErrNo cyg_devio_bread(cyg_io_handle_t handle, void *buf,
313                        cyg_uint32 *len, cyg_uint32 pos)
314 {
315     return -EDEVNOSUPP;
316 }
317
318 Cyg_ErrNo
319 cyg_devio_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
320 {
321     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
322     CYG_UNUSED_PARAM(cyg_uint32, which);
323     CYG_UNUSED_PARAM(CYG_ADDRWORD, info);
324     return -EDEVNOSUPP;
325 }
326
327 Cyg_ErrNo
328 cyg_devio_get_config(cyg_io_handle_t handle, cyg_uint32 key,
329                      void* buf, cyg_uint32* len)
330 {
331     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
332     CYG_UNUSED_PARAM(cyg_uint32, key);
333     CYG_UNUSED_PARAM(void*, buf);
334     CYG_UNUSED_PARAM(cyg_uint32*, len);
335     return -EDEVNOSUPP;
336 }
337
338 Cyg_ErrNo
339 cyg_devio_set_config(cyg_io_handle_t handle, cyg_uint32 key,
340                      void* buf, cyg_uint32* len)
341 {
342     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
343     CYG_UNUSED_PARAM(cyg_uint32, key);
344     CYG_UNUSED_PARAM(void*, buf);
345     CYG_UNUSED_PARAM(cyg_uint32*, len);
346     return -EDEVNOSUPP;
347 }
348
349 /*---------------------------------------------------------------------------*/
350 /* End of io/iosys.c */