/////////////////////////////////////////////////////////////////////////////////// // File : icu_driver.c // Date : 23/05/2013 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The icu_driver.c and icu_driver.h files are part ot the GIET-VM nano-kernel. // This driver supports the SoCLib vci_icu component, That is a vectorised // interrupt controler. // // It can exist several interrupt controller unit in the architecture // (one per cluster), and each one can contain several channels. // The number of ICU channels is equal to NB_PROCS_MAX, because there is // one private ICU channel per processor in a cluster. //////////////////////////////////////////////////////////////////////////////// // The virtual base address of the segment associated to the component is: // // seg_icu_base + cluster_xy * vseg_cluster_increment // // The seg_icu_base and vseg_cluster_increment values must be defined // in giet_vsegs.ld file. //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #if !defined(X_SIZE) # error: You must define X_SIZE in the hard_config.h file #endif #if !defined(Y_SIZE) # error: You must define X_SIZE in the hard_config.h file #endif #if !defined(X_WIDTH) # error: You must define X_WIDTH in the hard_config.h file #endif #if !defined(Y_WIDTH) # error: You must define X_WIDTH in the hard_config.h file #endif #if !defined(NB_PROCS_MAX) # error: You must define NB_PROCS_MAX in the hard_config.h file #endif #if !defined( USE_XICU ) # error: You must define USE_XICU in the hard_config.h file #endif //////////////////////////////////////////////////////////////////////////////// // _icu_set_mask() // This function set the mask register for the ICU channel identified // by the cluster index and the processor index. // All '1' bits are set / all '0' bits are not modified. // Returns 0 if success, > 0 if error. //////////////////////////////////////////////////////////////////////////////// unsigned int _icu_set_mask( unsigned int cluster_xy, unsigned int proc_id, unsigned int value ) { // parameters checking unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<= X_SIZE) return 1; if (y >= Y_SIZE) return 1; if (proc_id >= NB_PROCS_MAX) return 1; #if USE_XICU _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n"); return 1; #else unsigned int * icu_address = (unsigned int *) ((unsigned int)&seg_icu_base + (cluster_xy * (unsigned int)&vseg_cluster_increment)); icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; return 0; #endif } //////////////////////////////////////////////////////////////////////////////// // _icu_get_index() // This function returns the index of the highest priority (smaller index) IRQ. // The ICU channel is identified by the cluster index and the processor index. // Returns 0 if success, > 0 if error. //////////////////////////////////////////////////////////////////////////////// unsigned int _icu_get_index( unsigned int cluster_xy, unsigned int proc_id, unsigned int * buffer) { // parameters checking unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<= X_SIZE) return 1; if (y >= Y_SIZE) return 1; if (proc_id >= NB_PROCS_MAX) return 1; #if USE_XICU _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n"); return 1; #else unsigned int* icu_address = (unsigned int *) ((unsigned int)&seg_icu_base + (cluster_xy * (unsigned int)&vseg_cluster_increment)); *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; return 0; #endif } // 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