////////////////////////////////////////////////////////////////////////////////// // File : stdio.c // Date : 01/04/2010 // Author : alain greiner & Joel Porquet // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include //////////////////////////////////////////////////////////////////////////////////// ///////////////////// MIPS32 related system calls ///////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////// void giet_proc_xyp( unsigned int* cluster_x, unsigned int* cluster_y, unsigned int* lpid ) { sys_call( SYSCALL_PROC_XYP, (unsigned int)cluster_x, (unsigned int)cluster_y, (unsigned int)lpid, 0 ); } //////////////////////////// unsigned int giet_proctime() { return (unsigned int)sys_call( SYSCALL_PROC_TIME, 0, 0, 0, 0 ); } //////////////////////// unsigned int giet_rand() { unsigned int x = (unsigned int)sys_call( SYSCALL_PROC_TIME, 0, 0, 0, 0); if ((x & 0xF) > 7) { return (x*x & 0xFFFF); } else { return (x*x*x & 0xFFFF); } } ////////////////////////////////////////////////////////////////////////////////// ///////////////////// Task context system calls ///////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// unsigned int giet_proc_task_id() { return (unsigned int)sys_call( SYSCALL_LOCAL_TASK_ID, 0, 0, 0, 0 ); } ////////////////////////////////// unsigned int giet_global_task_id() { return (unsigned int)sys_call( SYSCALL_GLOBAL_TASK_ID, 0, 0, 0, 0 ); } ///////////////////////////// unsigned int giet_thread_id() { return (unsigned int)sys_call( SYSCALL_THREAD_ID, 0, 0, 0, 0 ); } //////////////////////////////////////////////////////////////////////////////////// ///////////////////// TTY device related system calls ///////////////////////////// //////////////////////////////////////////////////////////////////////////////////// ///////////////////// void giet_tty_alloc() { sys_call( SYSCALL_TTY_ALLOC, 0, 0 ,0 ,0 ); } //////////////////////////////////////////////////////////////////////// static int __printf( char* format, unsigned int channel, va_list* args) { int ret; // return value from the syscall printf_text: while (*format) { unsigned int i; for (i = 0 ; format[i] && (format[i] != '%') ; i++); if (i) { ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)format, i, channel, 0); if (ret != i) goto return_error; format += i; } if (*format == '%') { format++; goto printf_arguments; } } return 0; printf_arguments: { char buf[20]; char * pbuf; unsigned int len = 0; static const char HexaTab[] = "0123456789ABCDEF"; unsigned int i; switch (*format++) { case ('c'): /* char conversion */ { int val = va_arg( *args, int ); len = 1; buf[0] = val; pbuf = &buf[0]; break; } case ('d'): /* 32 bits decimal signed integer */ { int val = va_arg( *args, int ); if (val < 0) { val = -val; ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)"-", 1, channel, 0); if (ret != 1) goto return_error; } for(i = 0; i < 10; i++) { buf[9 - i] = HexaTab[val % 10]; if (!(val /= 10)) break; } len = i + 1; pbuf = &buf[9 - i]; break; } case ('u'): /* 32 bits decimal unsigned integer */ { unsigned int val = va_arg( *args, unsigned int ); for(i = 0; i < 10; i++) { buf[9 - i] = HexaTab[val % 10]; if (!(val /= 10)) break; } len = i + 1; pbuf = &buf[9 - i]; break; } case ('x'): /* 32 bits hexadecimal integer */ { unsigned int val = va_arg( *args, unsigned int ); ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)"0x", 2, channel, 0); if (ret != 2) goto return_error; for(i = 0; i < 8; i++) { buf[7 - i] = HexaTab[val % 16]; if (!(val /= 16)) break; } len = i + 1; pbuf = &buf[7 - i]; break; } case ('l'): /* 64 bits hexadecimal unsigned */ { unsigned long long val = va_arg( *args, unsigned long long ); ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)"0x", 2, channel, 0); if (ret != 2) goto return_error; for(i = 0; i < 16; i++) { buf[15 - i] = HexaTab[val % 16]; if (!(val /= 16)) break; } len = i + 1; pbuf = &buf[15 - i]; break; } case ('s'): /* string */ { char* str = va_arg( *args, char* ); while (str[len]) { len++; } pbuf = str; break; } default: goto return_error; } ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)pbuf, len, channel, 0); if (ret != len) goto return_error; goto printf_text; } return_error: return 1; } // end __printf() //////////////////////////////////////// void giet_tty_printf( char* format, ...) { va_list args; va_start( args, format ); int ret = __printf(format, 0xFFFFFFFF, &args); va_end( args ); if (ret) { giet_exit("ERROR in giet_tty_printf()"); } } // end giet_tty_printf() //////////////////////////////////////// void giet_shr_printf( char* format, ...) { va_list args; volatile unsigned int sr_save; sys_call( SYSCALL_TTY_GET_LOCK, 0, (unsigned int)&sr_save, 0, 0 ); va_start( args, format ); int ret = __printf(format, 0, &args); va_end( args ); sys_call( SYSCALL_TTY_RELEASE_LOCK, 0, (unsigned int)&sr_save, 0, 0 ); if (ret) { giet_exit("error in giet_shr_printf()"); } } // end giet_shr_printf() ///////////////////////////////// void giet_tty_getc( char * byte ) { int ret; do { ret = sys_call(SYSCALL_TTY_READ, (unsigned int)byte, // buffer address 1, // number of characters 0xFFFFFFFF, // channel index from task context 0); if ( ret < 0 ) giet_exit("error in giet_tty_getc()"); } while (ret != 1); } ///////////////////////////////////// void giet_tty_gets( char* buf, unsigned int bufsize ) { int ret; unsigned char byte; unsigned int index = 0; while (index < (bufsize - 1)) { do { ret = sys_call(SYSCALL_TTY_READ, (unsigned int)(&byte), 1, 0xFFFFFFFF, 0); if ( ret < 0 ) giet_exit("error in giet_tty_gets()"); } while (ret != 1); if (byte == 0x0A) /* LF */ { break; } else if ((byte == 0x7F) && (index > 0)) /* DEL */ { index--; } else { buf[index] = byte; index++; } } buf[index] = 0; } /////////////////////////////////////// void giet_tty_getw( unsigned int* val ) { unsigned char buf[32]; unsigned int string_byte = 0x00000000; // string containing one single byte unsigned int string_cancel = 0x00082008; // string containing BS/SPACE/BS unsigned int save = 0; unsigned int dec = 0; unsigned int done = 0; unsigned int overflow = 0; unsigned int length = 0; unsigned int i; unsigned int channel = 0xFFFFFFFF; int ret; // return value from syscalls // get characters while (done == 0) { // read one character do { ret = sys_call( SYSCALL_TTY_READ, (unsigned int)(&string_byte), 1, channel, 0); if ( ret < 0 ) giet_exit("error in giet_tty_getw()"); } while (ret != 1); // analyse character if ((string_byte > 0x2F) && (string_byte < 0x3A)) /* decimal character */ { buf[length] = (unsigned char)string_byte; length++; // echo ret = sys_call( SYSCALL_TTY_WRITE, (unsigned int)(&string_byte), 1, channel, 0 ); if ( ret < 0 ) giet_exit("error in giet_tty_gets()"); } else if (string_byte == 0x0A) /* LF character */ { done = 1; } else if ( (string_byte == 0x7F) || /* DEL character */ (string_byte == 0x08) ) /* BS character */ { if ( length > 0 ) { length--; // cancel the character ret = sys_call( SYSCALL_TTY_WRITE, (unsigned int)(&string_cancel), 3, channel, 0 ); if ( ret < 0 ) giet_exit("error in giet_tty_getw()"); } } // test buffer overflow if ( length >= 32 ) { overflow = 1; done = 1; } } // end while characters // string to int conversion with overflow detection if ( overflow == 0 ) { for (i = 0; (i < length) && (overflow == 0) ; i++) { dec = dec * 10 + (buf[i] - 0x30); if (dec < save) overflow = 1; save = dec; } } // final evaluation if ( overflow == 0 ) { // return value *val = dec; } else { // cancel all echo characters for (i = 0; i < length ; i++) { ret = sys_call( SYSCALL_TTY_WRITE, (unsigned int)(&string_cancel), 3, channel, 0 ); if ( ret < 0 ) giet_exit("error in giet_tty_getw()"); } // echo character '0' string_byte = 0x30; ret = sys_call( SYSCALL_TTY_WRITE, (unsigned int)(&string_byte), 1, channel, 0 ); if ( ret < 0 ) giet_exit("error in giet_tty_getw()"); // return 0 value *val = 0; } } ////////////////////////////////////////////////////////////////////////////////// ///////////////////// TIMER related system calls //////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// /////////////////////// void giet_timer_alloc() { if ( sys_call( SYSCALL_TIM_ALLOC, 0, 0, 0, 0 ) ) giet_exit("error in giet_timer_alloc()"); } //////////////////////////////////////////// void giet_timer_start( unsigned int period ) { if ( sys_call( SYSCALL_TIM_START, period, 0, 0, 0 ) ) giet_exit("error in giet_timer_start()"); } ////////////////////// void giet_timer_stop() { if ( sys_call( SYSCALL_TIM_STOP, 0, 0, 0, 0 ) ) giet_exit("error in giet_timer_stop()"); } ////////////////////////////////////////////////////////////////////////////////// /////////////// Frame buffer device related system calls /////////////////////// ////////////////////////////////////////////////////////////////////////////////// ///////////////////////// void giet_fbf_cma_alloc() { if ( sys_call( SYSCALL_FBF_CMA_ALLOC, 0, 0, 0, 0 ) ) giet_exit("error in giet_fbf_cma_alloc()"); } /////////////////////////////////////////// void giet_fbf_cma_start( void * buf0, void * buf1, unsigned int length ) { if ( sys_call( SYSCALL_FBF_CMA_START, (unsigned int)buf0, (unsigned int)buf1, length, 0 ) ) giet_exit("error in giet_fbf_cma_start()"); } //////////////////////////////////////////////// void giet_fbf_cma_display( unsigned int buffer ) { if ( sys_call( SYSCALL_FBF_CMA_DISPLAY, buffer, 0, 0, 0 ) ) giet_exit("error in giet_fbf_cma_display()"); } //////////////////////// void giet_fbf_cma_stop() { if ( sys_call( SYSCALL_FBF_CMA_STOP, 0, 0, 0, 0 ) ) giet_exit("error in giet_fbf_cma_stop()"); } ////////////////////////////////////////////// void giet_fbf_sync_write( unsigned int offset, void * buffer, unsigned int length ) { if ( sys_call( SYSCALL_FBF_SYNC_WRITE, offset, (unsigned int)buffer, length, 0 ) ) giet_exit("error in giet_fbf_sync_write()"); } ///////////////////////////////////////////// void giet_fbf_sync_read( unsigned int offset, void * buffer, unsigned int length ) { if ( sys_call( SYSCALL_FBF_SYNC_READ, offset, (unsigned int)buffer, length, 0 ) ) giet_exit("error in giet_fbf_sync_read()"); } ////////////////////////////////////////////////////////////////////////////////// /////////////////////// NIC related system calls ///////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////// unsigned int giet_nic_rx_alloc( unsigned int xmax, unsigned int ymax ) { int channel = sys_call( SYSCALL_NIC_ALLOC, 1, xmax, ymax, 0 ); if ( channel < 0 ) giet_exit("error in giet_nic_rx_alloc()"); return (unsigned int)channel; } //////////////////////////////////////////////////// unsigned int giet_nic_tx_alloc( unsigned int xmax, unsigned int ymax ) { int channel = sys_call( SYSCALL_NIC_ALLOC, 0, xmax, ymax, 0 ); if ( channel < 0 ) giet_exit("error in giet_nic_tx_alloc()"); return (unsigned int)channel; } ////////////////////////////////////////////// void giet_nic_rx_start( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_START, 1, channel, 0, 0 ) ) giet_exit("error in giet_nic_rx_start()"); } ////////////////////////////////////////////// void giet_nic_tx_start( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_START, 0, channel, 0, 0 ) ) giet_exit("error in giet_nic_tx_start()"); } /////////////////////////////////////////////////////////// void giet_nic_rx_move( unsigned int channel, void* buffer ) { if ( sys_call( SYSCALL_NIC_MOVE, 1, channel, (unsigned int)buffer, 0 ) ) giet_exit("error in giet_nic_rx_move()"); } /////////////////////////////////////////////////////////// void giet_nic_tx_move( unsigned int channel, void* buffer ) { if ( sys_call( SYSCALL_NIC_MOVE, 0, channel, (unsigned int)buffer, 0 ) ) giet_exit("error in giet_nic_tx_move()"); } ///////////////////////////////////////////// void giet_nic_rx_stop( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_STOP, 1, channel, 0, 0 ) ) giet_exit("error in giet_nic_rx_stop()"); } ///////////////////////////////////////////// void giet_nic_tx_stop( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_STOP, 0, channel, 0, 0 ) ) giet_exit("error in giet_nic_tx_stop()"); } ////////////////////////////////////////////// void giet_nic_rx_stats( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_STATS, 1, channel, 0, 0 ) ) giet_exit("error in giet_nic_rx_stats()"); } ////////////////////////////////////////////// void giet_nic_tx_stats( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_STATS, 0, channel, 0, 0 ) ) giet_exit("error in giet_nic_tx_stats()"); } ////////////////////////////////////////////// void giet_nic_rx_clear( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_CLEAR, 1, channel, 0, 0 ) ) giet_exit("error in giet_nic_rx_clear()"); } ////////////////////////////////////////////// void giet_nic_tx_clear( unsigned int channel ) { if ( sys_call( SYSCALL_NIC_CLEAR, 0, channel, 0, 0 ) ) giet_exit("error in giet_nic_tx_clear()"); } /////////////////////////////////////////////////////////////////////////////////// ///////////////////// FAT related system calls //////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// int giet_fat_open( const char* pathname, unsigned int flags ) { return sys_call( SYSCALL_FAT_OPEN, (unsigned int)pathname, flags, 0, 0 ); } //////////////////////////////////// void giet_fat_read( unsigned int fd, void* buffer, unsigned int count, unsigned int offset ) { if ( sys_call( SYSCALL_FAT_READ, fd, (unsigned int)buffer, count, offset ) != count ) giet_exit("ERROR in giet_fat_read()"); } ///////////////////////////////////// void giet_fat_write( unsigned int fd, void* buffer, unsigned int count, unsigned int offset ) { if ( sys_call( SYSCALL_FAT_WRITE, fd, (unsigned int)buffer, count, offset ) != count ) giet_exit("ERROR in giet_fat_write()"); } /* variant implementing the UNIX spec /////////////////////////////////////////////////////////////////////////////////// // This system call writes to a file identified by the "fd" file descriptor. // - "buffer" is the source buffer virtual address (must be word aligned). // - "count" is a number of bytes (must be multiple of 4). // It uses the implicit "lseek" pointer in file descriptor. /////////////////////////////////////////////////////////////////////////////////// void giet_fat_write( unsigned int fd, void* buffer, unsigned int count ) // number of bytes { return sys_call( SYSCALL_FAT_WRITE, fd, (unsigned int)buffer, count, 0 ); } */ ///////////////////////////////////// void giet_fat_lseek( unsigned int fd, unsigned int offset, unsigned int whence ) { if ( sys_call( SYSCALL_FAT_LSEEK, fd, offset, whence, 0 ) ) giet_exit("ERROR in giet_fat_lseek()"); } ////////////////////////////////////// void giet_fat_fstat( unsigned int fd ) { if ( sys_call( SYSCALL_FAT_FSTAT, fd, 0, 0, 0 ) ) giet_exit("ERROR in giet_fat_lseek()"); } ///////////////////////////////////// void giet_fat_close( unsigned int fd ) { if ( sys_call( SYSCALL_FAT_CLOSE, fd, 0, 0, 0 ) ) giet_exit("ERROR in giet_fat_close()"); } ////////////////////////////////////////////////////////////////////////////////// ///////////////////// Miscellaneous system calls ///////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// void giet_exit( char* string ) { sys_call( SYSCALL_EXIT, (unsigned int)string, 0, 0, 0 ); } ///////////////////////////////////////// void giet_assert( unsigned int condition, char* string ) { if ( condition == 0 ) giet_exit( string ); } ////////////////////////// void giet_context_switch() { sys_call( SYSCALL_CTX_SWITCH, 0, 0, 0, 0 ); } ///////////////////////////////////////////////// void giet_procs_number( unsigned int* x_size, unsigned int* y_size, unsigned int* nprocs ) { if ( sys_call( SYSCALL_PROCS_NUMBER, (unsigned int)x_size, (unsigned int)y_size, (unsigned int)nprocs, 0 ) ) giet_exit("ERROR in giet_procs_number()"); } //////////////////////////////////////////////////// void giet_vobj_get_vbase( char* vspace_name, char* vobj_name, unsigned int* vbase ) { if ( sys_call( SYSCALL_VOBJ_GET_VBASE, (unsigned int) vspace_name, (unsigned int) vobj_name, (unsigned int) vbase, 0 ) ) giet_exit("ERROR in giet_vobj_get_vbase()"); } //////////////////////////////////////////////////// void giet_vobj_get_length( char* vspace_name, char* vobj_name, unsigned int* length ) { if ( sys_call( SYSCALL_VOBJ_GET_LENGTH, (unsigned int) vspace_name, (unsigned int) vobj_name, (unsigned int) length, 0 ) ) giet_exit("ERROR in giet_vobj_get_length()"); } ///////////////////////////////////////// void giet_heap_info( unsigned int* vaddr, unsigned int* length, unsigned int x, unsigned int y ) { if ( sys_call( SYSCALL_HEAP_INFO, (unsigned int)vaddr, (unsigned int)length, x, y ) ) giet_exit("ERROR in giet_heap_info()"); } ///////////////////////////////////////// void giet_get_xy( void* ptr, unsigned int* px, unsigned int* py ) { if ( sys_call( SYSCALL_GET_XY, (unsigned int)ptr, (unsigned int)px, (unsigned int)py, 0 ) ) giet_exit("ERROR in giet_get_xy()"); } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4