]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/io/common/v2_0/src/iosys.c
unified MX27, MX25, MX37 trees
[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 //
202 // 'write' blocks to a device. The len and the position are in terms
203 // of blocks, not bytes like the cyg_io_write.
204 //
205 Cyg_ErrNo 
206 cyg_io_bwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len, cyg_uint32 pos)
207 {
208     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
209     // Validate request
210     if (!t->handlers->bwrite) {
211         return -EDEVNOSUPP;
212     }
213     // Special check.  If length is zero, this just verifies that the 
214     // 'bwrite' method exists for the given device.
215     if (NULL != len && 0 == *len) {
216         return ENOERR;
217     }
218     return t->handlers->bwrite(handle, buf, len, pos);
219 }
220
221 //
222 // 'read' blocks from a device. The len and the position are in terms of
223 // blocks, not bytes like the cyg_io_read.
224 //
225 Cyg_ErrNo 
226 cyg_io_bread(cyg_io_handle_t handle, void *buf, cyg_uint32 *len, cyg_uint32 pos)
227 {
228     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
229     // Validate request
230     if (!t->handlers->bread) {
231         return -EDEVNOSUPP;
232     }
233     // Special check.  If length is zero, this just verifies that the 
234     // 'bread' method exists for the given device.
235     if (NULL != len && 0 == *len) {
236         return ENOERR;
237     }
238     return t->handlers->bread(handle, buf, len, pos);
239 }
240
241 //
242 // Check device for available input or space for output
243 //
244
245 cyg_bool
246 cyg_io_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
247 {
248     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
249     // Validate request
250     if (!t->handlers->select) {
251         return -EDEVNOSUPP;
252     }
253
254     return t->handlers->select( handle, which, info );
255 }
256
257 //
258 // Get the configuration of a device.
259 //
260
261 Cyg_ErrNo 
262 cyg_io_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len)
263 {
264     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
265     // Validate request
266     if (!t->handlers->get_config) {
267         return -EDEVNOSUPP;
268     }
269     // Special check.  If length is zero, this just verifies that the 
270     // 'get_config' method exists for the given device.
271     if (NULL != len && 0 == *len) {
272         return ENOERR;
273     }
274     return t->handlers->get_config(handle, key, buf, len);
275 }
276
277 //
278 // Change the configuration of a device.
279 //
280
281 Cyg_ErrNo 
282 cyg_io_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len)
283 {
284     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
285     // Validate request
286     if (!t->handlers->set_config) {
287         return -EDEVNOSUPP;
288     }
289     // Special check.  If length is zero, this just verifies that the 
290     // 'set_config' method exists for the given device.
291     if (NULL != len && 0 == *len) {
292         return ENOERR;
293     }
294     return t->handlers->set_config(handle, key, buf, len);
295 }
296
297 /*---------------------------------------------------------------------------*/
298 // Default functions for devio tables
299
300 Cyg_ErrNo cyg_devio_cwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len)
301 {
302     return -EDEVNOSUPP;
303 }
304
305 Cyg_ErrNo cyg_devio_cread(cyg_io_handle_t handle, void *buf, cyg_uint32 *len)
306 {
307     return -EDEVNOSUPP;
308 }
309
310 Cyg_ErrNo cyg_devio_bwrite(cyg_io_handle_t handle, const void *buf,
311                         cyg_uint32 *len, cyg_uint32 pos)
312 {
313     return -EDEVNOSUPP;
314 }
315
316 Cyg_ErrNo cyg_devio_bread(cyg_io_handle_t handle, void *buf,
317                        cyg_uint32 *len, cyg_uint32 pos)
318 {
319     return -EDEVNOSUPP;
320 }
321
322 Cyg_ErrNo
323 cyg_devio_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
324 {
325     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
326     CYG_UNUSED_PARAM(cyg_uint32, which);
327     CYG_UNUSED_PARAM(CYG_ADDRWORD, info);
328     return -EDEVNOSUPP;
329 }
330
331 Cyg_ErrNo
332 cyg_devio_get_config(cyg_io_handle_t handle, cyg_uint32 key,
333                      void* buf, cyg_uint32* len)
334 {
335     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
336     CYG_UNUSED_PARAM(cyg_uint32, key);
337     CYG_UNUSED_PARAM(void*, buf);
338     CYG_UNUSED_PARAM(cyg_uint32*, len);
339     return -EDEVNOSUPP;
340 }
341
342 Cyg_ErrNo
343 cyg_devio_set_config(cyg_io_handle_t handle, cyg_uint32 key,
344                      void* buf, cyg_uint32* len)
345 {
346     CYG_UNUSED_PARAM(cyg_io_handle_t, handle);
347     CYG_UNUSED_PARAM(cyg_uint32, key);
348     CYG_UNUSED_PARAM(void*, buf);
349     CYG_UNUSED_PARAM(cyg_uint32*, len);
350     return -EDEVNOSUPP;
351 }
352
353 /*---------------------------------------------------------------------------*/
354 /* End of io/iosys.c */