1 /*==========================================================================
5 // Redboot syscall handling for GNUPro bsp support
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
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.
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
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.
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.
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.
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####
44 // Contributors: msalter
46 // Purpose: Temporary support for gnupro bsp
48 //####DESCRIPTIONEND####
50 //=========================================================================*/
53 #include <cyg/hal/hal_intr.h>
54 #include <cyg/hal/drv_api.h>
55 #include <cyg/hal/hal_stub.h>
57 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS
59 #define NEWLIB_EIO 5 /* I/O error */
60 #define NEWLIB_ENOSYS 88 /* Syscall not supported */
63 * Clients of this BSP will need to have access to BSP functions and
64 * data structures. Because, the client and the BSP may not be linked
65 * together, a structure of vectors is used to gain this access. A
66 * pointer to this structure can be gotten via a syscall. This syscall
67 * is made automatically from within the crt0.o file.
70 int version; /* version number for future expansion */
71 const void **__ictrl_table;
75 void *__console_procs;
77 void (*__flush_dcache)(void *__p, int __nbytes);
78 void (*__flush_icache)(void *__p, int __nbytes);
82 int (*__set_debug_comm)(int __comm_id);
83 int (*__set_console_comm)(int __comm_id);
84 int (*__set_serial_baud)(int __comm_id, int baud);
86 void (*__reset)(void);
87 int __console_interrupt_flag;
90 static __shared_t __shared_data = { 2 };
92 // this is used by newlib's mode_t so we should match it
94 #define _ST_INT32 __attribute__ ((__mode__ (__SI__)))
98 typedef unsigned int newlib_mode_t _ST_INT32;
99 typedef short newlib_dev_t;
100 typedef unsigned short newlib_ino_t;
101 typedef unsigned short newlib_nlink_t;
102 typedef long newlib_off_t;
103 typedef unsigned short newlib_uid_t;
104 typedef unsigned short newlib_gid_t;
105 typedef long newlib_time_t;
106 typedef long newlib_long_t;
112 newlib_mode_t st_mode;
113 newlib_nlink_t st_nlink;
116 newlib_dev_t st_rdev;
117 newlib_off_t st_size;
118 // We assume we've been compiled with the same flags as newlib here
119 #if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
120 newlib_time_t st_atime;
121 newlib_time_t st_mtime;
122 newlib_time_t st_ctime;
124 newlib_time_t st_atime;
125 newlib_long_t st_spare1;
126 newlib_time_t st_mtime;
127 newlib_long_t st_spare2;
128 newlib_time_t st_ctime;
129 newlib_long_t st_spare3;
130 newlib_long_t st_blksize;
131 newlib_long_t st_blocks;
132 newlib_long_t st_spare4[2];
135 #define NEWLIB_S_IFCHR 0020000 // character special file
137 static inline char __getc(void)
140 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
143 c = CYGACC_COMM_IF_GETC(*__chan);
145 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
146 c = CYGACC_COMM_IF_GETC(*__chan);
151 static inline void __putc(char c)
153 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
155 CYGACC_COMM_IF_PUTC(*__chan, c);
157 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
158 CYGACC_COMM_IF_PUTC(*__chan, c);
163 static inline void __flush(void)
165 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
168 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
170 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_FLUSH_OUTPUT);
175 static cyg_handle_t sys_timer_handle;
176 static cyg_interrupt sys_timer_interrupt;
177 static cyg_uint64 sys_timer_ticks = 0;
179 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
181 static unsigned int set_period = CYGNUM_HAL_RTC_PERIOD; // The default
183 typedef void *callback_func( char *pc, char *sp );
184 static callback_func *timer_callback = 0;
186 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
189 sys_timer_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
196 sys_timer_isr(cyg_vector_t vector, cyg_addrword_t data)
200 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
201 HAL_CLOCK_RESET(CYGNUM_HAL_INTERRUPT_RTC, set_period);
203 HAL_CLOCK_RESET(CYGNUM_HAL_INTERRUPT_RTC, CYGNUM_HAL_RTC_PERIOD);
204 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
206 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_RTC);
208 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
209 if ( timer_callback ) {
210 char *intrpc = (char *)0;
211 char *intrsp = (char *)0;
213 // There may be a number of ways to get the PC and (optional) SP
214 // information out of the HAL. Hence this is conditioned. In some
215 // configurations, a register-set pointer is available as
216 // (invisible) argument 3 to this ISR call.
218 #ifdef HAL_GET_PROFILE_INFO
219 HAL_GET_PROFILE_INFO( intrpc, intrsp );
220 #endif // HAL_GET_PROFILE_INFO available
222 CYGARC_HAL_SAVE_GP();
223 timer_callback( intrpc, intrsp );
224 CYGARC_HAL_RESTORE_GP();
226 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
227 return CYG_ISR_HANDLED;
231 static void sys_timer_init(void)
233 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
234 HAL_CLOCK_INITIALIZE(set_period);
236 HAL_CLOCK_INITIALIZE(CYGNUM_HAL_RTC_PERIOD);
237 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
239 cyg_drv_interrupt_create(
240 CYGNUM_HAL_INTERRUPT_RTC,
241 0, // Priority - unused
242 (CYG_ADDRWORD)0, // Data item passed to ISR & DSR
243 sys_timer_isr, // ISR
244 sys_timer_dsr, // DSR
245 &sys_timer_handle, // handle to intr obj
246 &sys_timer_interrupt ); // space for int obj
248 cyg_drv_interrupt_attach(sys_timer_handle);
250 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_RTC);
255 // read -- read bytes from the serial port. Ignore fd, since
256 // we only have stdin.
258 sys_read(int fd, char *buf, int nbytes)
262 for (i = 0; i < nbytes; i++) {
263 *(buf + i) = __getc();
264 if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) {
265 (*(buf + i + 1)) = 0;
274 // write -- write bytes to the serial port. Ignore fd, since
275 // stdout and stderr are the same. Since we have no filesystem,
276 // open will only return an error.
279 sys_write(int fd, char *buf, int nbytes)
299 // open -- open a file descriptor. We don't have a filesystem, so
300 // we return an error.
303 sys_open (const char *buf, int flags, int mode)
305 return (-NEWLIB_EIO);
309 // close -- We don't need to do anything, but pretend we did.
319 // lseek -- Since a serial port is non-seekable, we return an error.
322 sys_lseek(int fd, int offset, int whence)
324 return (-NEWLIB_EIO);
328 #define NS_PER_TICK (CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR)
329 #define TICKS_PER_SEC (1000000000ULL / NS_PER_TICK)
331 // This needs to match newlib HZ which is normally 60.
334 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
335 static unsigned int set_freq = TICKS_PER_SEC; // The default
336 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
338 sys_times(unsigned long *p)
340 static int inited = 0;
347 /* target clock runs at CLOCKS_PER_SEC. Convert to HZ */
349 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
350 *p = (sys_timer_ticks * HZ) / (cyg_uint64)set_freq;
352 *p = (sys_timer_ticks * HZ) / TICKS_PER_SEC;
353 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
358 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
360 static void sys_profile_call_back( char *func, char **previous_call_back )
362 if ( previous_call_back )
363 *previous_call_back = (char *)timer_callback;
365 timer_callback = (callback_func *)func;
367 // Ensure the timer is started
368 (void)sys_times( (unsigned long *)0 );
371 static void sys_profile_frequency( int freq, int *previous_freq )
374 // 0 => tell me the current value (no change, IMPLEMENTED HERE)
375 // - 1 => tell me the slowest (no change)
376 // - 2 => tell me the default (no change, IMPLEMENTED HERE)
377 // -nnn => tell me what you would choose for nnn (no change)
378 // MIN_INT => tell me the fastest (no change)
380 // 1 => tell me the slowest (sets the clock)
381 // MAX_INT => tell me the fastest (sets the clock)
383 // Ensure the timer is started
384 (void)sys_times( (unsigned long *)0 );
387 freq = TICKS_PER_SEC; // default value
388 else if ( 0 == freq )
389 freq = set_freq; // collect current value
391 int do_set_freq = (freq > 0);
392 unsigned int period = CYGNUM_HAL_RTC_PERIOD;
394 if ( 0 == (freq ^ -freq) ) // Then it's MIN_INT in local size
395 freq++; // just so that it will negate correctly
397 // Then set the timer to that fast - or pass on the enquiry
398 #ifdef HAL_CLOCK_REINITIALIZE
399 // Give the HAL enough info to do the division sum relative to
400 // the default setup, in period and TICKS_PER_SEC.
401 HAL_CLOCK_REINITIALIZE( freq, period, TICKS_PER_SEC );
403 freq = TICKS_PER_SEC; // the only choice
405 if ( do_set_freq ) { // update the global variables
406 unsigned int orig = set_freq;
409 // We must "correct" sys_timer_ticks for the new scale factor.
410 sys_timer_ticks = sys_timer_ticks * set_freq / orig;
414 if ( previous_freq ) // Return the current value (new value)
415 *previous_freq = freq;
418 void sys_profile_reset( void )
420 timer_callback = NULL;
421 // Want to preserve the frequency between runs, for clever GDB users!
422 // sys_profile_frequency( TICKS_PER_SEC, NULL );
425 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
428 // Generic syscall handler.
430 // Returns 0 if syscall number is not handled by this
431 // module, 1 otherwise. This allows applications to
432 // extend the syscall handler by using exception chaining.
435 __do_syscall(CYG_ADDRWORD func, // syscall function number
436 CYG_ADDRWORD arg1, CYG_ADDRWORD arg2, // up to four args.
437 CYG_ADDRWORD arg3, CYG_ADDRWORD arg4,
438 CYG_ADDRWORD *retval, CYG_ADDRWORD *sig) // syscall return value
447 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
448 __externC int cyg_hal_gdbfileio_open( const char *name, int flags,
449 int mode, int *sig );
451 err = cyg_hal_gdbfileio_open((const char *)arg1, (int)arg2, (int)arg3,
455 err = sys_open((const char *)arg1, (int)arg2, (int)arg3);
460 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
461 __externC int cyg_hal_gdbfileio_read( int fd, void *buf, size_t count,
464 err = cyg_hal_gdbfileio_read((int)arg1, (void *)arg2, (size_t)arg3,
468 err = sys_read((int)arg1, (char *)arg2, (int)arg3);
473 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
474 __externC int cyg_hal_gdbfileio_write( int fd, const void *buf,
475 size_t count, int *sig );
477 err = cyg_hal_gdbfileio_write((int)arg1, (const void *)arg2,
478 (size_t)arg3, (int *)sig);
481 err = sys_write((int)arg1, (char *)arg2, (int)arg3);
486 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
487 __externC int cyg_hal_gdbfileio_close( int fd, int *sig );
489 err = cyg_hal_gdbfileio_close((int)arg1, (int *)sig);
492 err = sys_close((int)arg1);
497 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
498 __externC int cyg_hal_gdbfileio_lseek( int fd, long offset,
499 int whence, int *sig );
501 err = cyg_hal_gdbfileio_lseek((int)arg1, (long)arg2, (int)arg3,
505 err = sys_lseek((int)arg1, (int)arg2, (int)arg3);
510 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
511 __externC int cyg_hal_gdbfileio_stat( const char *pathname,
512 void *statbuf, int *sig );
514 err = cyg_hal_gdbfileio_stat((const char *)arg1, (void *)arg2,
518 err = -NEWLIB_ENOSYS;
523 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
524 __externC int cyg_hal_gdbfileio_fstat( int fd, void *statbuf,
527 err = cyg_hal_gdbfileio_fstat((int)arg1, (void *)arg2,
532 struct newlib_stat *st = (struct newlib_stat *)arg2;
533 st->st_mode = NEWLIB_S_IFCHR;
534 st->st_blksize = 4096;
541 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
542 __externC int cyg_hal_gdbfileio_rename( const char *oldpath,
546 err = cyg_hal_gdbfileio_rename((const char *)arg1, (const char *)arg2,
550 err = -NEWLIB_ENOSYS;
555 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
556 __externC int cyg_hal_gdbfileio_unlink( const char *pathname,
559 err = cyg_hal_gdbfileio_unlink((const char *)arg1, (int *)sig);
562 err = -NEWLIB_ENOSYS;
567 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
568 __externC int cyg_hal_gdbfileio_isatty( int fd, int *sig );
570 err = cyg_hal_gdbfileio_isatty((int)arg1, (int *)sig);
578 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
579 __externC int cyg_hal_gdbfileio_system( const char *command,
582 err = cyg_hal_gdbfileio_system((const char *)arg1, (int *)sig);
588 case SYS_gettimeofday:
590 #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
591 __externC int cyg_hal_gdbfileio_gettimeofday( void *tv, void *tz,
594 err = cyg_hal_gdbfileio_gettimeofday((void *)arg1, (void *)arg2,
602 // FIXME. Some libglosses depend on this behavior.
603 err = sys_times((unsigned long *)arg1);
607 err = sys_times((unsigned long *)arg1);
612 *(unsigned long *)arg1 = (unsigned long)(ram_end-ram_start);
613 *(unsigned long *)arg2 = (unsigned long)ram_end;
615 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
616 case SYS_timer_call_back:
617 sys_profile_call_back( (char *)arg1, (char **)arg2 );
620 case SYS_timer_frequency:
621 sys_profile_frequency( (int)arg1, (unsigned int *)arg2 );
624 case SYS_timer_reset:
628 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
630 *(__shared_t **)arg1 = &__shared_data;
634 *sig = -1; // signal exit
638 #ifdef CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP
639 __send_exit_status((int)arg1);
643 #endif // CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP