/////////////////////////////////////////////////////////////////////////////////// // File : sys_handler.c // Date : 01/04/2012 // Author : alain greiner and joel porquet // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The sys_handler.c and sys_handler.h files are part of the GIET nano-kernel. // It define the syscall_vector[] (at the end of this file), as well as the // associated syscall handlers that are not related to peripherals. // The syscall handlers for peripherals are defined in the drivers.c file. /////////////////////////////////////////////////////////////////////////////////// #include //#include #include #include #include #include #include //////////////////////////////////////////////////////////////////////////// // Initialize the syscall vector with syscall handlers //////////////////////////////////////////////////////////////////////////// const void *_syscall_vector[32] = { &_procid, /* 0x00 */ &_proctime, /* 0x01 */ &_tty_write, /* 0x02 */ &_tty_read, /* 0x03 */ &_timer_write, /* 0x04 */ &_timer_read, /* 0x05 */ &_gcd_write, /* 0x06 */ &_gcd_read, /* 0x07 */ &_sys_ukn, /* 0x08 */ &_sys_ukn, /* 0x09 */ &_tty_read_irq, /* 0x0A */ &_sys_ukn, /* 0x0B */ &_sys_ukn, /* 0x0C */ &_ctx_switch, /* 0x0D */ &_exit, /* 0x0E */ &_procs_number, /* 0x0F */ &_fb_sync_write, /* 0x10 */ &_fb_sync_read, /* 0x11 */ &_fb_write, /* 0x12 */ &_fb_read, /* 0x13 */ &_fb_completed, /* 0x14 */ &_ioc_write, /* 0x15 */ &_ioc_read, /* 0x16 */ &_ioc_completed, /* 0x17 */ &_sys_ukn, /* 0x18 */ &_sys_ukn, /* 0x19 */ &_vobj_get_vbase, /* 0x1A */ &_sys_ukn, /* 0x1B */ &_sys_ukn, /* 0x1C */ &_sys_ukn, /* 0x1D */ &_sys_ukn, /* 0x1E */ &_sys_ukn, /* 0x1F */ }; ////////////////////////////////////////////////////////////////////////////// // function executed in case of undefined syscall ////////////////////////////////////////////////////////////////////////////// void _sys_ukn() { unsigned int epc; asm volatile("mfc0 %0, $14" : "=r"(epc)); _puts("\n\n!!! Undefined System Call !!!\n"); _puts("\nEPC = "); _putw( epc ); _exit(); } //////////////////////////////////////////////////////////////////////////// // _exit() // Task suicide... after printing a death message. //////////////////////////////////////////////////////////////////////////// void _exit() { unsigned int proc_id = _procid(); unsigned int task_id = _scheduler[proc_id].current; // print death message _puts("\n\n!!! Exit task "); _putw( task_id ); _puts(" on processor "); _putw( proc_id ); /* infinite loop */ while (1) asm volatile("nop"); } ////////////////////////////////////////////////////////////////////////////// // _procid() // Access CP0 and returns current processor's identifier. // Max number or processors is 1024. ////////////////////////////////////////////////////////////////////////////// unsigned int _procid() { unsigned int ret; asm volatile("mfc0 %0, $15, 1" : "=r"(ret)); return (ret & 0x3FF); } ////////////////////////////////////////////////////////////////////////////// // _proctime() // Access CP0 and returns current processor's elapsed clock cycles since boot. ////////////////////////////////////////////////////////////////////////////// unsigned int _proctime() { unsigned int ret; asm volatile("mfc0 %0, $9" : "=r"(ret)); return ret; } ////////////////////////////////////////////////////////////////////////////// // _procnumber() // returns in buffer argument the number of processors in the cluster // specified by the cluster_id argument. ////////////////////////////////////////////////////////////////////////////// unsigned int _procs_number( unsigned int cluster_id, unsigned int* buffer) { mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; mapping_cluster_t* cluster = _get_cluster_base( header ); if ( cluster_id < header->clusters ) { *buffer = cluster[cluster_id].procs; return 0; } else { return 1; } } ///////////////////////////////////////////////////////////////////////////// // _vobj_get_base() // returns 0: success, else: failed. // give access to the base address of a vobj identified by the (vspace_name / channel_name ) couple. // The "type" argument is here for checking purpose. ///////////////////////////////////////////////////////////////////////////// unsigned int _vobj_get_vbase( char* vspace_name, char* vobj_name, unsigned vobj_type, unsigned int* vobj_buffer) { mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; mapping_vspace_t* vspace = _get_vspace_base( header ); mapping_vobj_t* vobj = _get_vobj_base( header ); unsigned int vspace_id; unsigned int vobj_id; // scan vspaces for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ ) { if ( _strncmp( vspace[vspace_id].name, vspace_name, 31) == 0 ) { // scan vobjs for(vobj_id= vspace[vspace_id].vobj_offset; vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); vobj_id++) { if ( _strncmp( vobj[vobj_id].name, vobj_name, 31) == 0 ) { if(vobj[vobj_id].type != vobj_type) return -1;//wrong type *vobj_buffer = (unsigned int)vobj[vobj_id].vaddr; return 0; } } } } // not found !!! return -2; }