Changeset 188 for trunk/kernel
- Timestamp:
- Jul 12, 2017, 8:12:41 PM (7 years ago)
- Location:
- trunk/kernel
- Files:
-
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/devices/dev_dma.c
r23 r188 40 40 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 41 41 42 extern chdev_icu_input_t chdev_icu_input; // allocated in kernel_init.c43 44 42 //////////////////////////////////// 45 43 void dev_dma_init( chdev_t * chdev ) … … 64 62 } 65 63 66 // get DMA HWI IRQ index67 uint32_t hwi_id = chdev_icu_input.dma[channel];64 // bind IRQ to the core defined by the DMA channel 65 dev_pic_bind_irq( channel , chdev ); 68 66 69 // enable HWI IRQ in local ICU, and update interrupt vector 70 // the selected core is defined by the DMA channel index 71 dev_icu_enable_irq( channel , HWI_TYPE , hwi_id , chdev ); 67 // enable IRQ 68 dev_pic_enable_irq( channel, chdev ); 72 69 73 70 // create server thread … … 90 87 // start server thread 91 88 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 92 89 93 90 } // dev_dma_init() 94 91 -
trunk/kernel/devices/dev_fbf.c
r65 r188 41 41 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 42 42 43 extern chdev_pic_input_t chdev_input_irq; // allocated in kernel_init.c44 45 43 //////////////////////////////////// 46 void dev_fbf_init( chdev_t * chdev, 47 uint32_t width, 48 uint32_t height ) 44 void dev_fbf_init( chdev_t * chdev ) 49 45 { 50 46 // set FBF chdev extension fields 51 // TODO for the "width" and "height", fields,this should be done in the impementation47 // TODO this should be done in the impementation 52 48 // TODO specific part, as these parameters must be obtained from the hardware. 53 chdev->ext.fbf.width = width;54 chdev->ext.fbf.height = height;49 chdev->ext.fbf.width = CONFIG_FBF_WIDTH; 50 chdev->ext.fbf.height = CONFIG_FBF_HEIGHT; 55 51 56 52 // get implementation … … 59 55 // set chdev name 60 56 strcpy( chdev->name, "fbf" ); 57 61 58 // call driver init function 62 59 if( impl == IMPL_FBF_SCL ) -
trunk/kernel/devices/dev_fbf.h
r3 r188 90 90 91 91 /****************************************************************************************** 92 * This function completes the FBF chdev descriptor initialisation, 93 * namely the width and height parameters. 94 * TODO : these parameters should be provided by the hardware through a dedicated 95 * software API ... 92 * This function completes the FBF chdev descriptor initialisation. 96 93 * It calls the specific driver initialisation function, to initialise the hardware 97 94 * device and the specific data structures when required by the implementation. 98 95 * It must be called by a local thread. 96 * 97 * TODO In this first approach, the "width" and "height" parameters are defined 98 * by the CONFIG_FBF_WIDTH & CONFIG_FBF_HEIGHT in the kernel_config.h file. 99 * These parameters should be provided by the driver, accessing dedicated 100 * adressable registers in the FBF controler. 99 101 ****************************************************************************************** 100 102 * @ chdev : pointer on FBF chdev descriptor. 101 * @ width : number of pixels (bytes) per line.102 * @ height : total number of lines.103 103 *****************************************************************************************/ 104 void dev_fbf_init( struct chdev_s * chdev, 105 uint32_t width, 106 uint32_t height ); 104 void dev_fbf_init( struct chdev_s * chdev ); 107 105 108 106 /****************************************************************************************** -
trunk/kernel/devices/dev_ioc.c
r101 r188 39 39 ///////////////////////////////////////////////////////////////////////////////////////// 40 40 41 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 42 43 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 44 45 //////////////////////////////////// 46 void dev_ioc_init( chdev_t * chdev ) 47 { 48 // the local ICU chdev must be initialized before the IOC chdev, because 49 // the IOC chdev initialisation requires allocation of a WTI from local ICU 50 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 51 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before IOC" ); 41 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 42 43 ////////////////////////////////// 44 void dev_ioc_init( chdev_t * ioc ) 45 { 46 // the PIC chdev must be initialized before the IOC chdev, because 47 // the IOC chdev initialisation requires the routing of an external IRQ 48 xptr_t pic_xp = chdev_dir.pic; 49 50 assert( (pic_xp != XPTR_NULL) , __FUNCTION__ , "PIC not initialised before IOC" ); 52 51 53 52 // get implementation and channel from chdev descriptor 54 uint32_t impl = chdev->impl;55 uint32_t channel = chdev->channel;53 uint32_t impl = ioc->impl; 54 uint32_t channel = ioc->channel; 56 55 57 56 // set chdev name 58 s trcpy( chdev->name , "ioc");57 snprintf( ioc->name , 16 , "ioc_%d" , channel ); 59 58 60 59 // set driver specific fields in chdev descriptor and call driver init function 61 60 if( impl == IMPL_IOC_BDV ) 62 61 { 63 chdev->cmd = &soclib_bdv_cmd;64 chdev->isr = &soclib_bdv_isr;65 soclib_bdv_init( chdev);62 ioc->cmd = &soclib_bdv_cmd; 63 ioc->isr = &soclib_bdv_isr; 64 soclib_bdv_init( ioc ); 66 65 } 67 66 else if( impl == IMPL_IOC_HBA ) 68 67 { 69 chdev->cmd = &soclib_hba_cmd;70 chdev->isr = &soclib_hba_isr;71 soclib_hba_init( chdev);68 ioc->cmd = &soclib_hba_cmd; 69 ioc->isr = &soclib_hba_isr; 70 soclib_hba_init( ioc ); 72 71 } 73 72 else … … 76 75 } 77 76 78 // get a WTI mailbox from local ICU 79 uint32_t wti_id = dev_icu_wti_alloc(); 80 81 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 82 83 // select a core 77 // select a core to execute the IOC server thread 84 78 lid_t lid = cluster_select_local_core(); 85 79 86 // enable WTI IRQ and update WTI interrupt vector 87 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 88 89 // link IOC IRQ to WTI mailbox in PIC component 90 uint32_t irq_id = chdev_pic_input.ioc[channel]; 91 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 80 // bind the IOC IRQ to the selected core 81 dev_pic_bind_irq( lid , ioc ); 82 83 // enable IRQ 84 dev_pic_enable_irq( lid ,ioc ); 92 85 93 86 // create server thread … … 98 91 THREAD_DEV, 99 92 &chdev_sequencial_server, 100 chdev,93 ioc, 101 94 lid ); 95 102 96 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 103 97 104 // set "server" field in chdevdescriptor105 chdev->server = new_thread;98 // set "server" field in ioc descriptor 99 ioc->server = new_thread; 106 100 107 101 // start server thread -
trunk/kernel/devices/dev_ioc.h
r23 r188 108 108 typedef struct ioc_command_s 109 109 { 110 xptr_t dev_xp; /*! extended pointer on device descriptor*/110 xptr_t dev_xp; /*! extended pointer on IOC device descriptor */ 111 111 uint32_t type; /*! IOC_READ / IOC_WRITE / IOC_SYNC_READ */ 112 112 uint32_t lba; /*! first block index */ -
trunk/kernel/devices/dev_mmc.c
r23 r188 35 35 36 36 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 37 38 extern chdev_icu_input_t chdev_icu_input; // allocated in kernel_init.c39 37 40 38 //////////////////////////////////// … … 59 57 } 60 58 61 // get MMC HWI IRQ index 62 uint32_t hwi_id = chdev_icu_input.mmc; 63 64 // enable HWI IRQ to CP0 in local ICU, and update interrupt vector 65 dev_icu_enable_irq( 0 , HWI_TYPE , hwi_id , chdev ); 59 // bind IRQ to CP0 60 dev_pic_bind_irq( 0 , chdev ); 66 61 62 // enable IRQ 63 dev_pic_enable_irq( 0 , chdev ); 64 67 65 } // end dev_mmc_init() 68 66 -
trunk/kernel/devices/dev_nic.c
r23 r188 2 2 * dev_nic.c - NIC (Network Controler) generic device API implementation. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 36 36 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 37 37 38 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 39 40 //////////////////////////////////// 41 void dev_nic_init( chdev_t * chdev ) 38 ////////////////////////////////// 39 void dev_nic_init( chdev_t * nic ) 42 40 { 43 // the local ICU chdev must be initialized before the NIC chdev, because 44 // the NIC chdevs initialisation requires allocation of a WTI from local ICU 45 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 46 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" ); 41 // the PIC chdev must be initialized before the NIC chdev, because 42 // the NIC chdev initialisation requires the routing of an external IRQ. 43 xptr_t pic_xp = chdev_dir.pic; 44 45 assert( (pic_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" ); 47 46 48 47 // get "impl" , "channel" , "is_rx" fields from chdev descriptor 49 uint32_t impl = chdev->impl;50 uint32_t is_rx = chdev->is_rx;51 uint32_t channel = chdev->channel;48 uint32_t impl = nic->impl; 49 uint32_t channel = nic->channel; 50 bool_t is_rx = nic->is_rx; 52 51 53 52 // set chdev name 54 snprintf( chdev->name , 16 , "nic_%d" , chdev->channel ); 53 if( is_rx ) snprintf( nic->name , 16 , "nic_rx_%d" , channel ); 54 else snprintf( nic->name , 16 , "nic_tx_%d" , channel ); 55 55 56 56 // set driver specific fields in chdev descriptor and call driver init function 57 57 if( impl == IMPL_NIC_SOC ) 58 58 { 59 chdev->cmd = &soclib_nic_cmd;60 chdev->isr = &soclib_nic_isr;61 soclib_nic_init( chdev);59 nic->cmd = &soclib_nic_cmd; 60 nic->isr = &soclib_nic_isr; 61 soclib_nic_init( nic ); 62 62 } 63 63 else … … 66 66 } 67 67 68 // get a WTI mailbox from local ICU 69 uint32_t wti_id = dev_icu_wti_alloc(); 70 71 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 72 73 // select a core 68 // select a core to execute the NIC server thread 74 69 lid_t lid = cluster_select_local_core(); 75 70 76 // enable WTI IRQ and update WTI interrupt vector 77 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 78 79 // link NIC IRQ to WTI mailbox in PIC component 80 uint32_t irq_id; 81 if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel]; 82 else irq_id = chdev_pic_input.nic_tx[channel]; 83 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 71 // bind the NIC IRQ to the selected core 72 // but does NOT enable it 73 dev_pic_bind_irq( lid , nic ); 84 74 85 75 // create server thread … … 90 80 THREAD_DEV, 91 81 &chdev_sequencial_server, 92 chdev,82 nic, 93 83 lid ); 94 84 … … 96 86 97 87 // set "server" field in chdev descriptor 98 chdev->server = new_thread;88 nic->server = new_thread; 99 89 100 90 // start server thread … … 142 132 if( thread_ptr->command.nic.status == false ) 143 133 { 144 // get NIC-RX IRQ index and type145 uint32_t irq_type = dev_ptr->irq_type;146 uint32_t irq_id = dev_ptr->irq_id;147 148 134 // enable NIC-RX IRQ 149 dev_ icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );150 151 // block on THREAD_BLOCKED I/O condition and deschedule135 dev_pic_enable_irq( core->lid , dev_ptr ); 136 137 // block on THREAD_BLOCKED_IO condition and deschedule 152 138 thread_block( thread_ptr , THREAD_BLOCKED_IO ); 153 139 sched_yield(); 154 140 155 // disable NIC-RX channelIRQ156 dev_ icu_disable_irq( core->lid , irq_type , irq_id);141 // disable NIC-RX IRQ 142 dev_pic_disable_irq( core->lid , dev_ptr ); 157 143 } 158 144 … … 206 192 207 193 // call driver to test writable 208 thread_ptr->command.nic.cmd 194 thread_ptr->command.nic.cmd = NIC_CMD_WRITABLE; 209 195 dev_ptr->cmd( thread_xp ); 210 196 … … 216 202 if( thread_ptr->command.nic.status == false ) 217 203 { 218 // get NIC-TX IRQ index and type219 uint32_t irq_type = dev_ptr->irq_type;220 uint32_t irq_id = dev_ptr->irq_id;221 222 204 // enable NIC-TX IRQ 223 dev_ icu_enable_irq( core->lid , irq_type , irq_id ,dev_ptr );205 dev_pic_enable_irq( core->lid ,dev_ptr ); 224 206 225 207 // block on THREAD_BLOCKED I/O condition and deschedule … … 228 210 229 211 // disable NIC-TX IRQ 230 dev_ icu_disable_irq( core->lid , irq_type , irq_id);212 dev_pic_disable_irq( core->lid , dev_ptr ); 231 213 } 232 214 -
trunk/kernel/devices/dev_pic.c
r23 r188 24 24 #include <hal_types.h> 25 25 #include <hal_special.h> 26 #include <dev_icu.h>27 26 #include <chdev.h> 28 #include <memcpy.h>29 27 #include <printk.h> 30 28 #include <soclib_pic.h> 31 29 #include <dev_pic.h> 30 #include <cluster.h> 32 31 33 32 ///////////////////////////////////////////////////////////////////////////////////////// … … 37 36 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 38 37 39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c40 41 38 /////////////////////////////////// 42 void dev_pic_init( chdev_t * chdev, 43 uint32_t irq_nr ) 39 void dev_pic_init( chdev_t * pic ) 44 40 { 45 // set PIC chdev extension field46 chdev->ext.pic.irq_nr = irq_nr;47 48 41 // get implementation 49 uint32_t impl = chdev->impl;42 uint32_t impl = pic->impl; 50 43 51 44 // set chdev name 52 strcpy( chdev->name , "pic" ); 53 54 // call the relevant driver init function 55 if( impl == IMPL_PIC_SOC ) 45 strcpy( pic->name , "pic" ); 46 47 // call the relevant driver init function, 48 // and register commands in PIC device extension 49 if( impl == IMPL_PIC_SCL ) 56 50 { 57 soclib_pic_init( chdev ); 51 // call the PIC SOCLIB driver 52 soclib_pic_init( pic ); 53 54 // update the PIC chdev extension 55 pic->ext.pic.enable_timer = &soclib_pic_enable_timer; 56 pic->ext.pic.enable_irq = &soclib_pic_enable_irq; 57 pic->ext.pic.disable_irq = &soclib_pic_disable_irq; 58 pic->ext.pic.bind_irq = &soclib_pic_bind_irq; 59 pic->ext.pic.send_ipi = &soclib_pic_send_ipi; 60 pic->ext.pic.extend_init = &soclib_pic_extend_init; 61 } 62 else if( impl == IMPL_PIC_I86 ) 63 { 64 assert( false , __FUNCTION__ , "missing implementation for X86\n" ); 58 65 } 59 66 else 60 67 { 61 assert( false , __FUNCTION__ , " illegalPIC device implementation" );68 assert( false , __FUNCTION__ , "undefined PIC device implementation" ); 62 69 } 63 70 } // end dev_pic_init() 64 71 65 ///////////////////////////////////////// 66 void dev_pic_bind_irq( uint32_t irq_id, 67 cxy_t cxy, 68 uint32_t wti_id ) 72 ///////////////////////////////////////////////// 73 void dev_pic_extend_init( uint32_t * lapic_base ) 69 74 { 70 // get extended pointer on WTI mailbox71 xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ));75 // get pointer on PIC chdev 76 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 72 77 73 // get extended pointer on PIC chdev from directory 74 xptr_t dev_xp = chdev_dir.pic; 78 // call relevant driver function 79 pic->ext.pic.extend_init( lapic_base ); 80 } 75 81 76 // get PIC chdev cluster and local pointer 77 cxy_t dev_cxy = GET_CXY( dev_xp ); 78 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 82 ///////////////////////////////////// 83 void dev_pic_bind_irq( lid_t lid, 84 chdev_t * src_chdev ) 85 { 86 // get pointer on PIC chdev 87 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 79 88 80 // get implementation index and segment base 81 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 89 // call relevant driver function 90 pic->ext.pic.bind_irq( lid , src_chdev ); 91 } 82 92 83 // call the implementation specific driver function 84 if( impl == IMPL_PIC_SOC ) 85 {86 soclib_pic_bind_irq( dev_xp , irq_id , wti_xp ); 87 }88 } // end dev_pic_link_wti() 93 /////////////////////////////////////// 94 void dev_pic_enable_irq( lid_t lid, 95 chdev_t * src_chdev ) 96 { 97 // get pointer on PIC chdev 98 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 89 99 90 ////////////////////////////////////////// 91 void dev_pic_unbind_irq( uint32_t irq_id ) 100 // call relevant driver function 101 pic->ext.pic.enable_irq( src_chdev ); 102 } 103 104 //////////////////////////////////////// 105 void dev_pic_disable_irq( lid_t lid, 106 chdev_t * src_chdev ) 92 107 { 93 // get extended pointer on PIC chdev from directory94 xptr_t dev_xp = chdev_dir.pic;108 // get pointer on PIC chdev 109 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 95 110 96 // get PIC chdev cluster and local pointer97 cxy_t dev_cxy = GET_CXY( dev_xp);98 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 111 // call relevant driver function 112 pic->ext.pic.disable_irq( src_chdev ); 113 } 99 114 100 // get implementation index 101 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 115 //////////////////////////////////////////// 116 void dev_pic_enable_timer( uint32_t period ) 117 { 118 // get pointer on PIC chdev 119 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 102 120 103 // call the implementation specific driver function 104 if( impl == IMPL_PIC_SOC ) 105 { 106 soclib_pic_unbind_irq( dev_xp , irq_id ); 107 } 108 } // end dev_pic_disable_irq() 121 // call relevant driver function 122 pic->ext.pic.enable_timer( period ); 123 } 124 125 ////////////////////////////////// 126 void dev_pic_send_ipi( cxy_t cxy, 127 lid_t lid ) 128 { 129 // get pointer on PIC chdev 130 chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic ); 131 132 // call relevant driver function 133 pic->ext.pic.send_ipi( cxy , lid ); 134 } 109 135 110 136 -
trunk/kernel/devices/dev_pic.h
r14 r188 1 1 /* 2 * dev_pic.h - PIC ( ExternalInterrupt Controler) generic device API definition.2 * dev_pic.h - PIC (Programmable Interrupt Controler) generic device API definition. 3 3 * 4 4 * Authors Alain Greiner (2016) … … 29 29 30 30 /***************************************************************************************** 31 * Generic External Interrupt Controler definition 32 * 33 * The PIC generic device describes an external interrupt Controler, that translates 34 * N input IRQs generated by external peripherals to N WTI IRQs, that will be routed 35 * to a dynamically allocated WTI mailbox in a given cluster. 36 * 37 * The max number of input IRQs is defined by the CONFIG_MAX_IRQS_PER_PIC parameter. 38 * The actual number of connected IRQs is defined in the ''arch_info'' file, and stored 39 * in the PIC device extension. 40 * The "source" device for each input IRQ is also defined in the ''arch_info'' file, 41 * and are stored in the ''chdev_input_irq'' global variable in kernel initialization. 42 * 43 * This external peripheral does not execute I/O operations, but is just acting as a 44 * dynamically configurable interrupt router for another I/O operation. Therefore, 45 * ALMOS-MKH does not use the PIC device waiting queue, but call directly the relevant 46 * driver blocking functions to dynamically "bind" or "unbind" an external IRQ to a 47 * WTI mailbox. 31 * Generic Programmable Interrupt Controler definition 32 * 33 * The PIC generic device describes the the programmable hardware infrastructure used 34 * to route a given IRQ to a given core, in a given cluster, and to help the interrupt 35 * handler to select and execute the relevant ISR (Interrupt Service Routine). 36 * It handles the following type of interrupts: 37 * - External IRQs generated by the external (shared) peripherals. 38 * - Internal IRQs generated by the internal (replicated) peripherals. 39 * - Timer IRQs generated by the timers (one timer per core). 40 * - Inter Processor IRQs (IPI) generated by software. 41 * 42 * In most supported manycores architectures, the PIC device contains two types 43 * of hardware components: 44 * - the IOPIC is an external component, handling all external peripherals IRQs. 45 * - The LAPIC is an internal component, replicated in each cluster, handling local 46 * peripherals IRQS, Timer IRQs and IPIs (inter-processor-interupts). 47 * 48 * The "source" device for each input IRQ to the external IOPIC component, is defined 49 * in the "arch_info" file, and registered in the "iopic_input" global variable 50 * at kernel initialization. 51 * 52 * The "source" device for each input IRQ to the replicated LAPIC components, is defined 53 * in the "arch_info" file, and stored in the "lapic_input" global variable 54 * at kernel initialization. 55 * 56 * The PIC device defines 4 generic commands that can be used by each kernel instance, 57 * - to create in local cluster the PIC implementation specific interupt vector(s), 58 * - to bind a given IRQ (internal or external IRQ to a given core in the local cluster, 59 * - to configure and activate the TICK timer for a given core in the local cluster, 60 * - to allows the software to send an IPI to any core in any cluster. 61 * This API is detailed below, and must be implemented by all PIC implementations. 62 * 63 * In each cluster, a PIC implementation specific structure can be linked to the 64 * cluster manager or to the core descriptors to register the interrupt vectors 65 * used by the kernel to select the relevant ISR when an interrupt is received 66 * by a given core in agiven cluster. 67 68 * This PIC device does not execute itself I/O operations. It is just acting as a 69 * configurable interrupt router for I/O operation executed by other peripherals. 70 * Therefore, ALMOS-MKH does not use the PIC device waiting queue, does not creates 71 * a server thread for the PIC device, and does not register the command in the calling 72 * thread descriptor, but call directly the relevant driver function. 48 73 ****************************************************************************************/ 49 74 … … 53 78 54 79 /***************************************************************************************** 55 * This defines the (implementation independant) extension for the PIC device. 56 ****************************************************************************************/ 57 80 * This defines the specific extension for the PIC chdev descriptor. 81 * It contains four function pointers on the four PIC command types, 82 * that must be implemented by all drivers. 83 ****************************************************************************************/ 84 85 typedef void (pic_bind_t) ( lid_t lid , struct chdev_s * src_chdev ); 86 typedef void (pic_enable_t) ( struct chdev_s * src_chdev ); 87 typedef void (pic_disable_t) ( struct chdev_s * src_chdev ); 88 typedef void (pic_timer_t) ( uint32_t period ); 89 typedef void (pic_ipi_t) ( cxy_t cxy , lid_t lid ); 90 typedef void (pic_init_t) ( uint32_t * lapic_base ); 91 58 92 typedef struct pic_extend_s 59 93 { 60 uint32_t irq_nr; /*! actual number of input IRQs to the PIC device */ 94 pic_bind_t * bind_irq; /*! pointer on the driver "bind_irq" function */ 95 pic_enable_t * enable_irq; /*! pointer on the driver "enable_irq" function */ 96 pic_disable_t * disable_irq; /*! pointer on the driver "disable_irq" function */ 97 pic_timer_t * enable_timer; /*! pointer on the driver "enable_timer" function */ 98 pic_ipi_t * send_ipi; /*! pointer on the driver "send_ipi" function */ 99 pic_init_t * extend_init; /*! pointer on the driver "init_extend" function */ 61 100 } 62 101 pic_extend_t; 63 102 64 /***************************************************************************************** 65 * This enum defines the various implementations of the PIC external interrupt controller. 103 /****************************************************************************************** 104 * This structure defines the input IRQS for the external IOPIC controller, that is used 105 * by external peripherals (IOC, NIC, TXT, etc.) to signal completion of an I/O operation. 106 * It describes the hardware wiring of IRQs between external peripherals and the IOPIC, 107 * as each entry contains the input IRQ index in IOPIC. 108 * For a multi-channels peripheral, there is one chdev and one IRQ per channel. 109 * This structure is replicated in each cluster. It is allocated as a global variable 110 * in the kernel_init.c file. 111 *****************************************************************************************/ 112 113 typedef struct iopic_input_s 114 { 115 uint32_t txt[CONFIG_MAX_TXT_CHANNELS]; 116 uint32_t ioc[CONFIG_MAX_IOC_CHANNELS]; 117 uint32_t nic_rx[CONFIG_MAX_NIC_CHANNELS]; 118 uint32_t nic_tx[CONFIG_MAX_NIC_CHANNELS]; 119 uint32_t iob; 120 } 121 iopic_input_t; 122 123 /****************************************************************************************** 124 * This structure defines the input IRQS for the internal LAPIC controllers, that are used 125 * by internal peripherals IRQS (DMA, MMC) to signal completion of an I/O operation. 126 * It describes the hardware wiring of IRQs between internal peripherals and ICU, 127 * as each entry contains the input IRQ index in the LAPIC component. 128 * For a multi-channels peripheral, there is one chdev and one IRQ per channel. 129 * This structure is replicated in each cluster. It is allocated as a global variable 130 * in the kernel_init.c file. 131 *****************************************************************************************/ 132 133 typedef struct lapic_input_s 134 { 135 uint32_t dma[CONFIG_MAX_DMA_CHANNELS]; 136 uint32_t mmc; // MMC is single channel 137 } 138 lapic_input_t; 139 140 /***************************************************************************************** 141 * This enum defines the various implementations of the PIC device. 66 142 * This array must be kept consistent with the define in arch_info.h file 67 143 ****************************************************************************************/ … … 69 145 enum pic_impl_e 70 146 { 71 IMPL_PIC_S OC= 0,147 IMPL_PIC_SCL = 0, 72 148 IMPL_PIC_I86 = 1, 73 149 } … … 75 151 76 152 /***************************************************************************************** 77 * This function makes two initialisations :153 * This function makes two initialisations : 78 154 * - It initializes the PIC specific fields of the chdev descriptor. 79 * - it initializes the implementation specific PIC hardware device. 80 * It must be executed once in the kernel initialisation phase. 81 ***************************************************************************************** 82 * @ xp_dev : extended pointer on PIC device descriptor. 83 * @ uint32_t : actual number of input IRQs. 84 ****************************************************************************************/ 85 void dev_pic_init( struct chdev_s * chdev, 86 uint32_t irq_nr ); 87 88 /***************************************************************************************** 89 * This function link a WTI mailbox to the PIC input IRQ identified by its index, 90 * and unmask the selected input IRQ, calling the relevant driver. 91 ***************************************************************************************** 92 * @ irq_id : input IRQ index. 93 * @ cxy : WTI mailbox cluster. 94 * @ wti_id : WTI mailbox index in cluster. 95 ****************************************************************************************/ 96 void dev_pic_bind_irq( uint32_t irq_id, 97 cxy_t cxy, 98 uint32_t wti_id ); 99 100 /***************************************************************************************** 101 * This function mask a PIC input IRQ identified by its index, calling te relevant driver. 102 ***************************************************************************************** 103 * @ irq_id : input IRQ index. 104 ****************************************************************************************/ 105 void dev_pic_unbind_irq( uint32_t irq_id ); 106 155 * - it initializes the implementation specific PIC hardware registers. 156 * It is executed once in cluster containing the PIC chdev, during kernel initialisation. 157 * The calling core goes to sleep in case of failure. 158 ***************************************************************************************** 159 * @ pic : local pointer on PIC device descriptor. 160 ****************************************************************************************/ 161 void dev_pic_init( struct chdev_s * pic ); 162 163 /***************************************************************************************** 164 * This function completes the PIC infrastructure initialisation in each cluster. 165 * It allocates memory for the local PIC extensions in the core descriptors and/or 166 * in the cluster manager, as required by the specific PIC implementation. 167 * This function is called by CPO in all clusters, during kernel initialisation phase. 168 * The calling core goes to sleep in case of failure. 169 ***************************************************************************************** 170 * @ lapic_base : local pointer on LAPIC component segment base. 171 ****************************************************************************************/ 172 void dev_pic_extend_init( uint32_t * lapic_base ); 173 174 /***************************************************************************************** 175 * This function configure the PIC device to route the IRQ generated by a local chdev, 176 * defined by the <src_chdev> argument, to a local core identified by the <lid> argument. 177 * This is a static binding, defined during kernel init: IRQ can be enabled/disabled, 178 * but the binding cannot be released. It can be used for both internal & external IRQs. 179 * WARNING : the IRQ must be explicitely enabled by the dev_pic_enable_irq() function. 180 ***************************************************************************************** 181 * @ lid : target core local index. 182 * @ src_chdev : local pointer on source chdev descriptor. 183 ****************************************************************************************/ 184 void dev_pic_bind_irq( lid_t lid, 185 struct chdev_s * src_chdev ); 186 187 /***************************************************************************************** 188 * This function disables the IRQ generated by a local chdev, defined by the <src_chdev> 189 * argument. It can be used for both internal & external IRQs. 190 ***************************************************************************************** 191 * @ lid : target core local index. 192 * @ src_chdev : local pointer on source chdev descriptor. 193 ****************************************************************************************/ 194 void dev_pic_disable_irq( lid_t lid, 195 struct chdev_s * src_chdev ); 196 197 /***************************************************************************************** 198 * This function enables the IRQ generated by a local chdev, defined by the <src_chdev> 199 * argument. It can be used for both internal & external IRQs. 200 ***************************************************************************************** 201 * @ lid : target core local index. 202 * @ src_chdev : local pointer on source chdev descriptor. 203 ****************************************************************************************/ 204 void dev_pic_enable_irq( lid_t lid, 205 struct chdev_s * src_chdev ); 206 207 /***************************************************************************************** 208 * This function activates the TICK timer for the calling core. 209 * The <period> argument define the number of cycles between IRQs. 210 ***************************************************************************************** 211 * @ period : number of cycles between IRQs. 212 ****************************************************************************************/ 213 void dev_pic_enable_timer( uint32_t period ); 214 215 /***************************************************************************************** 216 * This function allows the calling thread to send an IPI to any core in any cluster. 217 * The target core is identified by the <cxy> & <lid> arguments. 218 ***************************************************************************************** 219 * @ cxy : target core cluster. 220 * @ lid : target core local index. 221 ****************************************************************************************/ 222 void dev_pic_send_ipi( cxy_t cxy, 223 lid_t lid ); 224 107 225 108 226 #endif /* _DEV_PIC_H_ */ -
trunk/kernel/devices/dev_txt.c
r101 r188 38 38 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 39 39 40 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 40 ////////////////////////////////// 41 void dev_txt_init( chdev_t * txt ) 42 { 43 // For all TXT channels other than the TXT0 (kernel terminal), 44 // the PIC chdev must be initialized before the TXT chdev, because 45 // the TXT chdev initialization requires the routing of an external IRQ 41 46 42 //////////////////////////////////// 43 void dev_txt_init( chdev_t * chdev ) 44 { 45 // the local ICU chdev must be initialized before the TXT chdev, because 46 // the TXT chdev initialization requires allocation of a WTI from local ICU 47 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 48 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before TXT" ); 47 xptr_t pic_xp = chdev_dir.pic; 48 uint32_t channel = txt->channel; 49 uint32_t impl = txt->impl; 49 50 50 // get implementation and channel index 51 uint32_t impl = chdev->impl; 52 uint32_t channel = chdev->channel; 51 assert( (pic_xp != XPTR_NULL) || (channel == 0) , __FUNCTION__ , 52 "PIC not initialised before TXT" ); 53 53 54 54 // set chdev name 55 snprintf( chdev->name , 16 , "txt_%d" , chdev->channel );55 snprintf( txt->name , 16 , "txt_%d" , channel ); 56 56 57 57 // set fields "cmd", "isr", and call driver init function 58 58 if( impl == IMPL_TXT_TTY ) 59 59 { 60 chdev->cmd = &soclib_tty_cmd;61 chdev->isr = &soclib_tty_isr;62 soclib_tty_init( chdev);60 txt->cmd = &soclib_tty_cmd; 61 txt->isr = &soclib_tty_isr; 62 soclib_tty_init( txt ); 63 63 } 64 64 else … … 67 67 } 68 68 69 // get a WTI mailbox from local ICU 70 uint32_t wti_id = dev_icu_wti_alloc(); 69 // no server thread and no IRQ routing for TXT0 70 if( channel != 0 ) 71 { 72 // select a core to execute the TXT server thread 73 lid_t lid = cluster_select_local_core(); 71 74 72 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 75 // bind TXT IRQ to the selected core 76 dev_pic_bind_irq( lid , txt ); 73 77 74 // select a core75 lid_t lid = cluster_select_local_core();78 // enable TXT IRQ 79 dev_pic_enable_irq( lid , txt ); 76 80 77 // enable WTI IRQ and update WTI interrupt vector 78 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 81 // create server thread 82 thread_t * new_thread; 83 error_t error; 79 84 80 // link IOC IRQ to WTI mailbox in PIC component 81 uint32_t irq_id = chdev_pic_input.txt[channel]; 82 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 85 error = thread_kernel_create( &new_thread, 86 THREAD_DEV, 87 &chdev_sequencial_server, 88 txt, 89 lid ); 83 90 84 // create server thread 85 thread_t * new_thread; 86 error_t error; 91 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 87 92 88 error = thread_kernel_create( &new_thread, 89 THREAD_DEV, 90 &chdev_sequencial_server, 91 chdev, 92 lid ); 93 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 93 // set "server" field in chdev descriptor 94 txt->server = new_thread; 94 95 95 // set "server" field in chdev descriptor 96 chdev->server = new_thread; 97 98 // start server thread 99 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 96 // start server thread 97 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 98 } 100 99 } 101 100 -
trunk/kernel/kern/chdev.h
r23 r188 120 120 uint32_t channel; /*! channel index */ 121 121 bool_t is_rx; /*! relevant for NIC peripheral channels only */ 122 xptr_t base; /*! extended pointer on channel segment paddr*/122 xptr_t base; /*! extended pointer on channel device segment */ 123 123 char name[16]; /*! name (required by DEVFS) */ 124 124 … … 177 177 178 178 /****************************************************************************************** 179 * This structure defines the input IRQS for the PIC device, that is used by all external180 * peripherals (IOC, NIC, TXT, etc.) to signal completion of an I/O operation. It describes181 * the hardware wiring of IRQs between external peripherals and PIC, as each entry in this182 * structure contains the input IRQ index in PIC. Value is -1 for an unused input.183 * For a multi-channels peripheral, there is one chdev and one IRQ per channel.184 * This structure is replicated in each cluster. It is allocated as a global variable185 * in the kernel_init.c file, and is initialised during kernel init.186 *****************************************************************************************/187 188 typedef struct chdev_pic_input_s189 {190 uint32_t txt[CONFIG_MAX_TXT_CHANNELS];191 uint32_t ioc[CONFIG_MAX_IOC_CHANNELS];192 uint32_t nic_rx[CONFIG_MAX_NIC_CHANNELS];193 uint32_t nic_tx[CONFIG_MAX_NIC_CHANNELS];194 }195 chdev_pic_input_t;196 197 /******************************************************************************************198 * This structure defines the input IRQS for the ICU device, that is used by all internal199 * peripherals IRQS (DMA, MMC, etc.) to signal completion of an I/O operation. It describes200 * the hardware wiring of IRQs between internal peripherals and ICU, as each entry in this201 * structure contains the input IRQ index in ICU. Value is -1 for an unused input.202 * For a multi-channels peripheral, there is one chdev and one IRQ per channel.203 * This structure is replicated in each cluster. It is allocated as a global variable204 * in the kernel_init.c file, and is initialised during kernel init.205 *****************************************************************************************/206 207 typedef struct chdev_icu_input_s208 {209 uint32_t dma[CONFIG_MAX_DMA_CHANNELS];210 uint32_t mmc; // MMC is single channel211 }212 chdev_icu_input_t;213 214 /******************************************************************************************215 179 * This function display relevant values for a chdev descriptor. 216 180 ****************************************************************************************** -
trunk/kernel/kern/cluster.h
r101 r188 133 133 134 134 pmgr_t pmgr; /*! embedded process manager */ 135 136 void * pic_extend; /*! PIC implementation specific extension */ 135 137 } 136 138 cluster_t; -
trunk/kernel/kern/core.c
r126 r188 30 30 #include <thread.h> 31 31 #include <chdev.h> 32 #include <dev_ icu.h>32 #include <dev_pic.h> 33 33 #include <rpc.h> 34 34 #include <cluster.h> … … 50 50 core->usage = 0; 51 51 core->spurious_irqs = 0; 52 core->rpc_threads = 0; 53 54 list_root_init( &core->rpc_free_list ); 55 56 core->thread_rpc = NULL; 52 core->rpc_threads = 0; 57 53 core->thread_idle = NULL; 58 54 core->fpu_owner = NULL; 59 55 core->rand_last = hal_time_stamp() & 0xFFF; 60 56 57 // initialize scheduler 61 58 sched_init( core ); 62 59 } … … 167 164 } 168 165 166 167 /* deprecated [AG] july 20017 169 168 /////////////////////////////////////////////////// 170 169 void core_set_irq_vector_entry( core_t * core, … … 177 176 else core->pti_vector[irq_id] = chdev; 178 177 } 178 */ -
trunk/kernel/kern/core.h
r101 r188 36 36 struct thread_s; 37 37 struct chdev_s; 38 38 enum pic_impl_e; 39 39 40 40 /**************************************************************************************** 41 41 * This structure defines the core descriptor. 42 * - It contains an embedded private scheduler. 43 * - It contains the three interrupt vectors, implemented as three arrays of pointers 44 * on the source channel devices, for all IRQs allocated to the core. 42 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler. 43 * It contains an architecture specific extension to store the interrupt vector(s). 44 * The core_init()function must allocate memory for this extension, depending on the 45 * PIC device implementation type. 45 46 ***************************************************************************************/ 46 47 … … 55 56 uint32_t usage; /*! cumulated busy_percent (idle / total) */ 56 57 uint32_t spurious_irqs; /*! for instrumentation... */ 58 uint32_t rpc_threads; /*! current RPC threads number for this core */ 57 59 struct thread_s * thread_rpc; /*! pointer on current RPC thread descriptor */ 58 60 struct thread_s * thread_idle; /*! pointer on idle thread descriptor */ 59 61 struct thread_s * fpu_owner; /*! pointer on current FPU owner thread */ 60 62 uint32_t rand_last; /*! last computed random value */ 61 uint32_t rpc_threads; /*! total number of RPC threads for this core */62 list_entry_t rpc_free_list; /*! root of the list of free RPC threads */63 64 63 scheduler_t scheduler; /*! embedded private scheduler */ 65 64 66 struct chdev_s * hwi_vector[CONFIG_MAX_HWIS_PER_ICU]; /*! on source device */ 67 struct chdev_s * pti_vector[CONFIG_MAX_PTIS_PER_ICU]; /*! on source device */ 68 struct chdev_s * wti_vector[CONFIG_MAX_WTIS_PER_ICU]; /*! on source device */ 65 void * pic_extend; /*! PIC implementation specific extension */ 69 66 } 70 67 core_t; 71 68 72 /*************************************************************************************** 69 /**************************************************************************************** 73 70 * This macro returns a pointer on the calling core descriptor. 74 ************************************************************************************** /71 ***************************************************************************************/ 75 72 76 73 #define CURRENT_CORE (CURRENT_THREAD->core) 77 74 78 75 /*************************************************************************************** 79 * TODO this initialisation must be completed for the thread_idle field... [AG] 80 * This function initializes a core descriptor from information found in arch_info. 76 * This function initializes a core descriptor. 81 77 * It makes the association [gid] <=> [lid], as defined in arch_info, via the 82 78 * boot_info_t structure build by the bootloader in each cluster. 79 * It allocates memory for the PIC infrastructure specific core extension. 80 * It does NOT initialize the <thread_idle> and the <pic_extend> fields, 81 * that must be completed later. 83 82 *************************************************************************************** 84 83 * @ core : pointer on core descriptor to initialise. 85 * @ lid : local core index 86 * @ gid : global core identifier (hardware index) 84 * @ lid : local core index in cluster. 85 * @ gid : global core identifier (hardware index). 87 86 **************************************************************************************/ 88 void core_init( core_t * core,89 lid_t lid,90 gid_t gid );87 void core_init( core_t * core, 88 lid_t lid, 89 gid_t gid ); 91 90 92 91 /*************************************************************************************** -
trunk/kernel/kern/do_interrupt.c
r140 r188 30 30 void do_interrupt( thread_t * this ) 31 31 { 32 // update user time33 thread_user_time_update( this );34 35 // access ICU device to call the relevant ISR36 dev_icu_irq_handler();37 38 // handle pending signals for interrupted thread39 thread_signals_handle( this );40 41 // update kernel time42 thread_kernel_time_update( this );43 32 } -
trunk/kernel/kern/kernel_init.c
r127 r188 85 85 cluster_t cluster_manager CONFIG_CACHE_LINE_ALIGNED; 86 86 87 // This variable defines the TXT0 kernel terminal 88 __attribute__((section(".kdata"))) 89 chdev_t txt0_chdev CONFIG_CACHE_LINE_ALIGNED; 90 87 91 // This variables define the kernel process0 descriptor 88 92 __attribute__((section(".kdata"))) … … 93 97 chdev_directory_t chdev_dir CONFIG_CACHE_LINE_ALIGNED; 94 98 95 // This variable contains the input IRQ indexes for the PIC device99 // This variable contains the input IRQ indexes for the IOPIC controller 96 100 __attribute__((section(".kdata"))) 97 chdev_pic_input_t chdev_pic_inputCONFIG_CACHE_LINE_ALIGNED;98 99 // This variable contains the input IRQ indexes for the ICU device101 iopic_input_t iopic_input CONFIG_CACHE_LINE_ALIGNED; 102 103 // This variable contains the input IRQ indexes for the LAPIC controller 100 104 __attribute__((section(".kdata"))) 101 chdev_icu_input_t chdev_icu_inputCONFIG_CACHE_LINE_ALIGNED;105 lapic_input_t lapic_input CONFIG_CACHE_LINE_ALIGNED; 102 106 103 107 // This variable defines the local cluster identifier 104 108 __attribute__((section(".kdata"))) 105 109 cxy_t local_cxy CONFIG_CACHE_LINE_ALIGNED; 106 107 // This variable defines the TXT0 chdev descriptor108 __attribute__((section(".kdata")))109 chdev_t txt0_chdev CONFIG_CACHE_LINE_ALIGNED;110 110 111 111 // This variable is used for CP0 cores synchronisation in kernel_init() … … 142 142 143 143 /////////////////////////////////////////////////////////////////////////////////////////// 144 // This static function initializes the TXT0 chdev descriptor, associated to the "kernel 145 // terminal", and shared by all kernel instances for debug messages. It also registers it 146 // in the chdev directory, containing extended pointers on all chdevs. 147 // The global variable txt0_chdev is replicated in all clusters, but only the chdev 148 // allocated in I/O cluster is used by ALMOS-MKH. 149 // Therefore, this function must be called by a thread running in the I/O cluster. 144 // This function initializes the TXT0 chdev descriptor, that is the "kernel terminal", 145 // shared by all kernel instances for debug messages. 146 // It is a global variable (replicated in all clusters), because this terminal is used 147 // before the kmem allocator initialisation, but only the instance in cluster containing 148 // the calling core is registered in the "chdev_dir" directory. 150 149 // As this TXT0 chdev supports only the TXT_SYNC_WRITE command, we don't create 151 150 // a server thread, we don't allocate a WTI, and we don't initialize the waiting queue. … … 158 157 uint32_t dev_nr; // actual number of devices in this cluster 159 158 xptr_t base; // remote pointer on segment base 160 uint32_t type; // peripheral type161 159 uint32_t func; // device functional index 162 160 uint32_t impl; // device implementation index … … 164 162 uint32_t x; // X cluster coordinate 165 163 uint32_t y; // Y cluster coordinate 164 uint32_t channels; // number of channels 166 165 167 166 // get number of peripherals and base of devices array from boot_info … … 173 172 { 174 173 base = dev_tbl[i].base; 175 type = dev_tbl[i].type;176 func = FUNC_FROM_TYPE(type );177 impl = IMPL_FROM_TYPE( type );174 func = FUNC_FROM_TYPE( dev_tbl[i].type ); 175 impl = IMPL_FROM_TYPE( dev_tbl[i].type ); 176 channels = dev_tbl[i].channels; 178 177 179 178 if (func == DEV_FUNC_TXT ) 180 179 { 181 // initialize basic fields 182 txt0_chdev.func = func; 183 txt0_chdev.impl = impl; 184 txt0_chdev.channel = 0; 185 txt0_chdev.is_rx = 0; 186 txt0_chdev.base = base; 187 188 // initialize lock 180 assert( (channels > 0) , __FUNCTION__ , 181 "numner of TXT channels cannot be 0\n"); 182 183 // initializes TXT0 basic fields 184 txt0_chdev.func = func; 185 txt0_chdev.impl = impl; 186 txt0_chdev.channel = 0; 187 txt0_chdev.base = base; 188 txt0_chdev.is_rx = false; 189 190 // initializes lock 189 191 remote_spinlock_init( XPTR( local_cxy , &txt0_chdev.wait_lock ) ); 190 191 // TODO use generic device initialisation 192 // hal_drivers_txt_init( &txt0_chdev ); 193 194 if( impl == IMPL_TXT_TTY ) 195 { 196 txt0_chdev.cmd = &soclib_tty_cmd; 197 txt0_chdev.isr = &soclib_tty_isr; 198 soclib_tty_init( &txt0_chdev ); 199 } 200 201 // initialize the replicated chdev_dir[x][y] structures 192 193 // TXT specific initialisation: 194 // no server thread & no IRQ routing for channel 0 195 dev_txt_init( &txt0_chdev ); 196 197 // register the TXT0 in all chdev_dir[x][y] structures 202 198 for( x = 0 ; x < info->x_size ; x++ ) 203 199 { … … 210 206 } 211 207 212 kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev" 213 " / paddr = %l at cycle %d\n", 214 __FUNCTION__ , local_cxy , chdev_func_str( func ), 215 XPTR(local_cxy , &txt0_chdev) , hal_get_cycles() ); 216 } 217 } 218 } 219 220 /////////////////////////////////////////////////////////////////////////////////////////// 221 // This static function allocates memory for the chdev (channel_device) descriptors 222 // associated to the internal peripherals contained in the local cluster. These internal 223 // devices (ICU, MMC, DMA) chdev descriptors are placed in the local cluster. 224 // It initialises these device descriptors as specified by the boot_info_t structure, 225 // including the dynamic linking with the driver for the specified implementation. 226 // Finally, all copies of the devices directory are initialised. 208 kinit_dmsg("\n[INFO] %s created TXT0 chdev in cluster %x at cycle %d\n", 209 __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() ); 210 } 211 } // end loop on devices 212 } // end txt0_device_init() 213 214 /////////////////////////////////////////////////////////////////////////////////////////// 215 // This function allocates memory and initializes the chdev descriptors for the internal 216 // peripherals contained in the local cluster, other than the LAPIC, as specified by 217 // the boot_info, including the linking with the driver for the specified implementation. 218 // The relevant entries in all copies of the devices directory are initialised. 227 219 /////////////////////////////////////////////////////////////////////////////////////////// 228 220 // @ info : pointer on the local boot-info structure. … … 230 222 static void internal_devices_init( boot_info_t * info ) 231 223 { 232 boot_device_t * dev; // pointer on boot_info device (ICU/MMC/DMA) 233 uint32_t x; // X cluster coordinate 234 uint32_t y; // Y cluster coordinate 235 chdev_t * chdev_ptr; // local pointer on chdev descriptor 236 xptr_t chdev_xp; // extended pointer on chdev descriptor 237 238 /////////// ICU ////////// 239 240 dev = &info->dev_icu; 241 242 assert( ((info->cores_nr == 0) || (dev->channels != 0)) , __FUNCTION__ , 243 "ICU device must exist in cluster containing cores" ); 244 245 assert( (dev->channels == 1) , __FUNCTION__ , 246 "channels number must be 1 for ICU device" ); 247 248 assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_ICU ) , __FUNCTION__ , 249 " inconsistent ICU device type"); 250 251 // create one chdev in local cluster 252 chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ), 253 IMPL_FROM_TYPE( dev->type ), 254 0, // channel 255 false, // TX 256 dev->base ); 257 258 assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate ICU chdev" ); 259 260 // get extended pointer on chdev descriptor 261 chdev_xp = XPTR( local_cxy , chdev_ptr ); 262 263 // make ICU specific initialisation 264 // TODO remove these three parameters 265 dev_icu_init( chdev_ptr , dev->param0 , dev->param1 , dev->param2 ); 266 267 // initialize the ICU field in the chdev_dir[x][y] structures 268 // replicated in all clusters, and containing extended pointers 269 // on all remotely accessible devices 270 for( x = 0 ; x < info->x_size ; x++ ) 271 { 272 for( y = 0 ; y < info->y_size ; y++ ) 273 { 274 cxy_t cxy = (x<<info->y_width) + y; 275 hal_remote_swd( XPTR( cxy , &chdev_dir.icu[local_cxy] ) , chdev_xp ); 276 } 277 } 278 279 // initialize the entries of the local chdev_icu_input structure 280 // defining how internal peripherals are connected to ICU 281 uint32_t id; 282 uint8_t valid; 283 uint32_t src_type; 284 uint8_t src_ch; 285 uint32_t src_func; 286 for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ ) 287 { 288 valid = dev->irq[id].valid; 289 src_type = dev->irq[id].dev_type; 290 src_ch = dev->irq[id].channel; 291 src_func = FUNC_FROM_TYPE( src_type ); 292 293 if( valid ) // only valid local IRQs are registered 294 { 295 if ( src_func == DEV_FUNC_MMC ) chdev_icu_input.mmc = id; 296 else if( src_func == DEV_FUNC_DMA ) chdev_icu_input.dma[src_ch] = id; 297 else assert( false , __FUNCTION__ , "illegal source device for ICU input" ); 298 } 299 } 300 301 kinit_dmsg("\n[INFO] %s : core[%x][0] created ICU chdev at cycle %d\n", 302 __FUNCTION__ , local_cxy , hal_get_cycles() ); 303 304 /////////// MMC internal chdev /////////// 305 306 dev = &info->dev_mmc; 307 308 if( dev->channels != 0 ) // MMC device is defined 309 { 310 assert( (dev->channels == 1) , __FUNCTION__ , 311 "channels number must be 1 for MMC device" ); 312 313 assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_MMC ) , __FUNCTION__ , 314 " inconsistent MMC device type"); 315 316 // create one chdev in local cluster 317 chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ), 318 IMPL_FROM_TYPE( dev->type ), 319 0, // channel 320 false, // TX 321 dev->base ); 322 323 assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate MMC chdev" ); 324 325 // get extended pointer on chdev descriptor 326 chdev_xp = XPTR( local_cxy , chdev_ptr ); 327 328 // make MMC specific initialisation 329 dev_mmc_init( chdev_ptr ); 330 331 // initialize the MMC field in the chdev_dir[x][y] structures 332 // replicated in all clusters, and containing extended pointers 333 // on all remotely accessible devices 334 for( x = 0 ; x < info->x_size ; x++ ) 335 { 336 for( y = 0 ; y < info->y_size ; y++ ) 224 boot_device_t * dev_tbl; // pointer on array of internaldevices in boot_info 225 uint32_t dev_nr; // actual number of devices in this cluster 226 xptr_t base; // remote pointer on segment base 227 uint32_t func; // device functionnal index 228 uint32_t impl; // device implementation index 229 uint32_t i; // device index in dev_tbl 230 uint32_t x; // X cluster coordinate 231 uint32_t y; // Y cluster coordinate 232 uint32_t channels; // number of channels 233 uint32_t channel; // channel index 234 chdev_t * chdev_ptr; // local pointer on created chdev 235 236 // get number of internal peripherals and base from boot_info 237 dev_nr = info->int_dev_nr; 238 dev_tbl = info->int_dev; 239 240 // loop on internal peripherals 241 for( i = 0 ; i < dev_nr ; i++ ) 242 { 243 base = dev_tbl[i].base; 244 channels = dev_tbl[i].channels; 245 func = FUNC_FROM_TYPE( dev_tbl[i].type ); 246 impl = IMPL_FROM_TYPE( dev_tbl[i].type ); 247 248 ////////////////////////// 249 if( func == DEV_FUNC_MMC ) 250 { 251 assert( (channels == 1) , __FUNCTION__ , 252 "MMC device must be single channel\n" ); 253 254 // create chdev in local cluster 255 chdev_ptr = chdev_create( func, 256 impl, 257 0, // channel 258 false, // direction 259 base ); 260 261 assert( (chdev_ptr != NULL) , __FUNCTION__ , 262 "cannot allocate memory for MMC chdev\n" ); 263 264 // make MMC specific initialisation 265 dev_mmc_init( chdev_ptr ); 266 267 // set the MMC field in all chdev_dir[x][y] structures 268 for( x = 0 ; x < info->x_size ; x++ ) 337 269 { 338 cxy_t cxy = (x<<info->y_width) + y; 339 hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ) , chdev_xp ); 270 for( y = 0 ; y < info->y_size ; y++ ) 271 { 272 cxy_t cxy = (x<<info->y_width) + y; 273 hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ), 274 XPTR( local_cxy , chdev_ptr ) ); 275 } 340 276 } 341 } 342 343 kinit_dmsg("\n[INFO] %s : core[%x][0] created MMC chdev at cycle %d\n", 344 __FUNCTION__ , local_cxy , hal_get_cycles() ); 345 } 346 347 /////////// DMA internal chdevs ////////// 348 349 dev = &info->dev_dma; 350 351 if( dev->channels != 0 ) // DMA device is defined 352 { 353 assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_DMA ) , __FUNCTION__ , 354 " inconsistent DMA device type"); 355 356 // create one chdev per channel in local cluster 357 uint32_t channel; 358 for( channel = 0 ; channel < dev->channels ; channel++ ) 359 { 360 chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ), 361 IMPL_FROM_TYPE( dev->type ), 362 channel, // channel 363 false, // TX 364 dev->base ); 365 366 assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate DMA chdev" ); 367 368 // get extended pointer on channel descriptor 369 chdev_xp = XPTR( local_cxy , chdev_ptr ); 370 371 // make DMA specific initialisation 372 dev_dma_init( chdev_ptr ); 373 374 // initialize only the DMA[channel] field in the local chdev_dir[x][y] 375 // structure because the DMA device is not remotely accessible. 376 chdev_dir.dma[channel] = chdev_xp; 377 378 kinit_dmsg("\n[INFO] %s : core[%x][0] created DMA[%d] chdev at cycle %d\n", 379 __FUNCTION__ , local_cxy , channel , hal_get_cycles() ); 277 278 if( local_cxy == 0 ) 279 kinit_dmsg("\n[INFO] %s created MMC chdev in cluster 0 at cycle %d\n", 280 __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() ); 281 } 282 /////////////////////////////// 283 else if( func == DEV_FUNC_DMA ) 284 { 285 // create one chdev per channel in local cluster 286 for( channel = 0 ; channel < channels ; channel++ ) 287 { 288 // create chdev[channel] in local cluster 289 chdev_ptr = chdev_create( func, 290 impl, 291 channel, 292 false, // direction 293 base ); 294 295 assert( (chdev_ptr != NULL) , __FUNCTION__ , 296 "cannot allocate memory for DMA chdev" ); 297 298 // make DMA specific initialisation 299 dev_dma_init( chdev_ptr ); 300 301 // initialize only the DMA[channel] field in the local chdev_dir[x][y] 302 // structure because the DMA device is not remotely accessible. 303 chdev_dir.dma[channel] = XPTR( local_cxy , chdev_ptr ); 304 305 kinit_dmsg("\n[INFO] %s created DMA[%d] chdev in cluster 0 at cycle %d\n", 306 __FUNCTION__ , channel , (uint32_t)hal_time_stamp() ); 307 } 380 308 } 381 309 } … … 383 311 384 312 /////////////////////////////////////////////////////////////////////////////////////////// 385 // This static function allocates memory for the chdev descriptors associated 386 // to the external (shared) peripherals contained in the local cluster. These external 387 // devices (IOB, IOC, TXT, NIC, etc ) are distributed on all clusters. 388 // It initialises these device descriptors as specified by the boot_info_t structure, 313 // This function allocates memory and initializes the chdev descriptors for the 314 // external (shared) peripherals other than the IOPIC, as specified by the boot_info, 389 315 // including the dynamic linking with the driver for the specified implementation. 390 // Finally, all copies of the devices directory are initialised. 391 // 392 // The number of channel_devices depends on the device functional type. 393 // There are three nested loops to build the full set of external channel_devices: 394 // - loop on external devices. 395 // - loop on channels for multi-channels devices. 396 // - loop on directions (RX/TX) for NIC device. 397 // The set of channel_devices is indexed by the chdev_gid global index, that is used 398 // to select the cluster containing a given chdev[func,channel,direction]. 399 // All clusters scan the full set of chdevs, but only the cluster matching 400 // (chdev_gid % (x_size*y_size)) create the corresponding chdev. 401 // 402 // TODO check that cluster IO contains a PIC [AG] 403 // TODO make a default initialisation for the chdev_dir structure (XPTR_NULL ) [AG] 316 // These chdev descriptors are distributed on all clusters, using a modulo on a global 317 // index, identically computed in all clusters: In each cluster, the local CP0 core 318 // computes the global index for all external chdevs, and creates only the chdevs that 319 // must be placed in the local cluster. 320 // The relevant entries in all copies of the devices directory are initialised. 404 321 /////////////////////////////////////////////////////////////////////////////////////////// 405 322 // @ info : pointer on the local boot-info structure. … … 407 324 static void external_devices_init( boot_info_t * info ) 408 325 { 409 boot_device_t * dev_tbl; // pointer on array of devices in boot_info 410 uint32_t dev_nr; // actual number of devices in this cluster 411 xptr_t base; // remote pointer on segment base 412 uint32_t type; // peripheral type 326 boot_device_t * dev_tbl; // pointer on array of external devices in boot_info 327 uint32_t dev_nr; // actual number of external devices 328 xptr_t base; // remote pointer on segment base 413 329 uint32_t func; // device functionnal index 414 330 uint32_t impl; // device implementation index 415 uint32_t i; // device index in dev_tbl 416 uint32_t x; // X cluster coordinate 417 uint32_t y; // Y cluster coordinate 418 uint32_t channels_nr; // number of channels 419 uint32_t channel; // channel index 420 uint32_t directions_nr; // number of directions 421 uint32_t direction; // direction index 422 uint32_t p0; // device parameter 0 423 uint32_t p1; // device parameter 1 424 uint32_t p2; // device parameter 2 425 uint32_t p3; // device parameter 3 426 uint32_t first_channel; // used in loop on channels 427 331 uint32_t i; // device index in dev_tbl 332 uint32_t x; // X cluster coordinate 333 uint32_t y; // Y cluster coordinate 334 uint32_t channels; // number of channels 335 uint32_t channel; // channel index 336 uint32_t directions; // number of directions (1 or 2) 337 uint32_t rx; // direction index (0 or 1) 338 uint32_t first_channel; // used in loop on channels for TXT 428 339 chdev_t * chdev; // local pointer on one channel_device descriptor 429 xptr_t chdev_xp; // extended pointer on channel_device descriptor 430 uint32_t chdev_gid = 0; // global index of channel_device descriptor 340 uint32_t ext_chdev_gid; // global index of external chdev 431 341 432 342 // get number of peripherals and base of devices array from boot_info … … 434 344 dev_tbl = info->ext_dev; 435 345 346 // initializes global index (PIC is already placed in cluster 0 347 ext_chdev_gid = 1; 348 436 349 // loop on external peripherals 437 350 for( i = 0 ; i < dev_nr ; i++ ) 438 351 { 439 base = dev_tbl[i].base; 440 type = dev_tbl[i].type; 441 channels_nr = dev_tbl[i].channels; 442 p0 = dev_tbl[i].param0; 443 p1 = dev_tbl[i].param1; 444 p2 = dev_tbl[i].param2; 445 p3 = dev_tbl[i].param3; 446 447 func = FUNC_FROM_TYPE( type ); 448 impl = IMPL_FROM_TYPE( type ); 352 base = dev_tbl[i].base; 353 channels = dev_tbl[i].channels; 354 func = FUNC_FROM_TYPE( dev_tbl[i].type ); 355 impl = IMPL_FROM_TYPE( dev_tbl[i].type ); 449 356 450 357 // There is one chdev per direction for NIC 451 if (func == DEV_FUNC_NIC) directions _nr= 2;452 else directions _nr= 1;358 if (func == DEV_FUNC_NIC) directions = 2; 359 else directions = 1; 453 360 454 361 // The TXT0 chdev has already been created … … 456 363 else first_channel = 0; 457 364 458 // do nothing for RO M, that does not require a device descriptor.365 // do nothing for RO, that does not require a device descriptor. 459 366 if( func == DEV_FUNC_ROM ) continue; 460 367 461 // check external device functional type 462 if( (func != DEV_FUNC_IOB) && 463 (func != DEV_FUNC_PIC) && 464 (func != DEV_FUNC_IOC) && 465 (func != DEV_FUNC_TXT) && 466 (func != DEV_FUNC_NIC) && 467 (func != DEV_FUNC_FBF) ) 468 { 469 assert( false , __FUNCTION__ , "undefined external peripheral type" ); 470 } 368 // do nothing for PIC, that is already initialized 369 if( func == DEV_FUNC_PIC ) continue; 370 371 // check PIC device initialized 372 assert( (chdev_dir.pic != XPTR_NULL ) , __FUNCTION__ , 373 "PIC device must be initialized before other devices\n" ); 374 375 // check external device functionnal type 376 assert( ( (func == DEV_FUNC_IOB) || 377 (func == DEV_FUNC_IOC) || 378 (func == DEV_FUNC_TXT) || 379 (func == DEV_FUNC_NIC) || 380 (func == DEV_FUNC_FBF) ) , __FUNCTION__ , 381 "undefined external peripheral type\n" ); 471 382 472 383 // loops on channels 473 for( channel = first_channel ; channel < channels _nr; channel++ )384 for( channel = first_channel ; channel < channels ; channel++ ) 474 385 { 475 386 // loop on directions 476 for( direction = 0 ; direction < directions_nr ; direction++ )387 for( rx = 0 ; rx < directions ; rx++ ) 477 388 { 478 // gettarget cluster for chdev[func,channel,direction]479 uint32_t offset = chdev_gid % ( info->x_size * info->y_size );389 // compute target cluster for chdev[func,channel,direction] 390 uint32_t offset = ext_chdev_gid % ( info->x_size * info->y_size ); 480 391 uint32_t cx = offset / info->y_size; 481 392 uint32_t cy = offset % info->y_size; … … 489 400 impl, 490 401 channel, 491 direction,402 rx, // direction 492 403 base ); 493 404 … … 495 406 "cannot allocate external device" ); 496 407 497 // get extended pointer on chdev498 chdev_xp = XPTR( local_cxy , chdev );499 500 408 // make device type specific initialisation 501 // the number of parameters depends on the device type502 // TODO : remove the parameters that must be provided by the drivers503 409 if ( func == DEV_FUNC_IOB ) dev_iob_init( chdev ); 504 410 else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev ); 505 411 else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev ); 506 412 else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev ); 507 else if( func == DEV_FUNC_PIC ) dev_pic_init( chdev , p0 ); 508 else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev , p0 , p1 ); 509 else 510 { 511 assert( false , __FUNCTION__ , "undefined device type" ); 512 } 413 else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev ); 513 414 514 415 // all external (shared) devices are remotely accessible … … 517 418 xptr_t * entry; 518 419 519 if( func == DEV_FUNC_IOB) entry = &chdev_dir.iob;520 if( func == DEV_FUNC_PIC ) entry = &chdev_dir.pic;521 if( func == DEV_FUNC_TXT) entry = &chdev_dir.txt[channel];522 if( func == DEV_FUNC_IOC ) entry = &chdev_dir.ioc[channel];523 if( func == DEV_FUNC_FBF ) entry = &chdev_dir.fbf[channel];524 if( func == DEV_FUNC_NIC ) entry = &chdev_dir.nic_tx[channel];420 if(func==DEV_FUNC_IOB ) entry = &chdev_dir.iob; 421 if(func==DEV_FUNC_IOC ) entry = &chdev_dir.ioc[channel]; 422 if(func==DEV_FUNC_TXT ) entry = &chdev_dir.txt[channel]; 423 if(func==DEV_FUNC_FBF ) entry = &chdev_dir.fbf[channel]; 424 if((func==DEV_FUNC_NIC) && (rx==0)) entry = &chdev_dir.nic_tx[channel]; 425 if((func==DEV_FUNC_NIC) && (rx==1)) entry = &chdev_dir.nic_rx[channel]; 525 426 526 427 for( x = 0 ; x < info->x_size ; x++ ) … … 529 430 { 530 431 cxy_t cxy = (x<<info->y_width) + y; 531 hal_remote_swd( XPTR( cxy , entry ) , chdev_xp ); 432 hal_remote_swd( XPTR( cxy , entry ), 433 XPTR( local_cxy , chdev ) ); 532 434 } 533 435 } 534 436 535 kinit_dmsg("\n[INFO] %s : core[%x][0] create chdev %s[%d]at cycle %d\n",536 __FUNCTION__ , local_cxy , chdev_func_str( func ),537 channel , hal_get_cycles() );437 kinit_dmsg("\n[INFO] %s create chdev %s[%d] in cluster %x at cycle %d\n", 438 __FUNCTION__ , chdev_func_str( func ), channel, 439 local_cxy , (uint32_t)hal_time_stamp() ); 538 440 539 441 } // end if match 540 442 541 443 // increment chdev global index (matching or not) 542 chdev_gid++;444 ext_chdev_gid++; 543 445 544 446 } // end loop on directions 545 546 447 } // end loop on channels 547 548 // initialize the entries of the local chdev_pic_input structure 549 // defining how external peripherals are connected to PIC 448 } // end loop on devices 449 } // end external_devices_init() 450 451 /////////////////////////////////////////////////////////////////////////////////////////// 452 // This function is called by CP0 in cluster 0 to allocate memory and initialize the PIC 453 // device, namely the informations attached to the external IOPIC controller. 454 // This initialisation must be done before other devices initialisation because the IRQ 455 // routing infrastructure is required for internal and external devices initialisation. 456 /////////////////////////////////////////////////////////////////////////////////////////// 457 // @ info : pointer on the local boot-info structure. 458 /////////////////////////////////////////////////////////////////////////////////////////// 459 static void iopic_init( boot_info_t * info ) 460 { 461 boot_device_t * dev_tbl; // pointer on boot_info external devices array 462 uint32_t dev_nr; // actual number of external devices 463 xptr_t base; // remote pointer on segment base 464 uint32_t func; // device functionnal index 465 uint32_t impl; // device implementation index 466 uint32_t i; // device index in dev_tbl 467 uint32_t x; // cluster X coordinate 468 uint32_t y; // cluster Y coordinate 469 bool_t found; // IOPIC found 470 chdev_t * chdev; // pointer on PIC chdev descriptor 471 472 // get number of external peripherals and base of array from boot_info 473 dev_nr = info->ext_dev_nr; 474 dev_tbl = info->ext_dev; 475 476 // loop on external peripherals to get the IOPIC 477 for( i = 0 , found = false ; i < dev_nr ; i++ ) 478 { 479 func = FUNC_FROM_TYPE( dev_tbl[i].type ); 480 550 481 if( func == DEV_FUNC_PIC ) 551 482 { 552 uint32_t id; 553 uint8_t valid; 554 uint32_t dev_type; 555 uint8_t channel; 556 uint8_t is_rx; 557 558 // loop on PIC inputs 559 for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ ) 483 base = dev_tbl[i].base; 484 impl = IMPL_FROM_TYPE( dev_tbl[i].type ); 485 found = true; 486 break; 487 } 488 } 489 490 assert( found , __FUNCTION__ , "PIC device not found\n" ); 491 492 // allocate and initialize the PIC chdev in local cluster 493 chdev = chdev_create( func, 494 impl, 495 0, // channel 496 0, // direction, 497 base ); 498 499 assert( (chdev != NULL), __FUNCTION__ , "no memory for PIC chdev\n" ); 500 501 // make PIC device type specific initialisation 502 dev_pic_init( chdev ); 503 504 // register extended pointer on PIC chdev in "chdev_dir" array in all clusters 505 xptr_t * entry = &chdev_dir.pic; 506 507 for( x = 0 ; x < info->x_size ; x++ ) 508 { 509 for( y = 0 ; y < info->y_size ; y++ ) 510 { 511 cxy_t cxy = (x<<info->y_width) + y; 512 hal_remote_swd( XPTR( cxy , entry ) , 513 XPTR( local_cxy , chdev ) ); 514 } 515 } 516 517 // initialize the "iopic_input" structure 518 // defining how external IRQs are connected to IOPIC 519 uint32_t id; 520 uint8_t valid; 521 uint32_t type; 522 uint8_t channel; 523 uint8_t is_rx; 524 525 for( id = 0 ; id < CONFIG_MAX_EXTERNAL_IRQS ; id++ ) 526 { 527 valid = dev_tbl[i].irq[id].valid; 528 type = dev_tbl[i].irq[id].dev_type; 529 channel = dev_tbl[i].irq[id].channel; 530 is_rx = dev_tbl[i].irq[id].is_rx; 531 532 if( valid ) // only valid inputs are registered 533 { 534 uint32_t * index; // local pointer on one entry 535 uint16_t func = FUNC_FROM_TYPE( type ); 536 537 if ( func == DEV_FUNC_TXT ) 538 index = &iopic_input.txt[channel]; 539 else if( func == DEV_FUNC_IOC ) 540 index = &iopic_input.ioc[channel]; 541 else if( (func == DEV_FUNC_NIC) && (is_rx == 0) ) 542 index = &iopic_input.nic_tx[channel]; 543 else if( (func == DEV_FUNC_NIC) && (is_rx != 0) ) 544 index = &iopic_input.nic_rx[channel]; 545 else if( func == DEV_FUNC_IOB ) 546 index = &iopic_input.iob; 547 else 548 assert( false , __FUNCTION__ , "illegal source device for IOPIC input" ); 549 550 // set entry in local structure 551 *index = id; 552 } 553 } 554 555 kinit_dmsg("\n[INFO] %s created IOPIC chdev in cluster %x at cycle %d\n", 556 __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() ); 557 558 } // end iopic_init() 559 560 /////////////////////////////////////////////////////////////////////////////////////////// 561 // This function is called by all CP0s in all cluster to complete the PIC device 562 // initialisation, namely the informations attached to the LAPIC controller. 563 // This initialisation must be done after the IOPIC initialisation, but before other 564 // devices initialisation because the IRQ routing infrastructure is required for both 565 // internal and external devices initialisation. 566 /////////////////////////////////////////////////////////////////////////////////////////// 567 // @ info : pointer on the local boot-info structure. 568 /////////////////////////////////////////////////////////////////////////////////////////// 569 static void lapic_init( boot_info_t * info ) 570 { 571 boot_device_t * dev_tbl; // pointer on boot_info internal devices array 572 uint32_t dev_nr; // number of internal devices 573 uint32_t i; // device index in dev_tbl 574 xptr_t base; // remote pointer on segment base 575 uint32_t func; // device functionnal type in boot_info 576 bool_t found; // LAPIC found 577 578 // get number of internal peripherals and base 579 dev_nr = info->int_dev_nr; 580 dev_tbl = info->int_dev; 581 582 // loop on internal peripherals to get the lapic device 583 for( i = 0 , found = false ; i < dev_nr ; i++ ) 584 { 585 func = FUNC_FROM_TYPE( dev_tbl[i].type ); 586 587 if( func == DEV_FUNC_ICU ) 588 { 589 base = dev_tbl[i].base; 590 found = true; 591 break; 592 } 593 } 594 595 // if the LAPIC controller is not defined in the boot_info, 596 // we simply don't initialize the PIC extensions in the kernel, 597 // making the assumption that the LAPIC related informations 598 // are hidden in the hardware specific PIC driver. 599 if( found ) 600 { 601 // initialise the PIC extensions for 602 // the core descriptor and core manager extensions 603 dev_pic_extend_init( (uint32_t *)GET_PTR( base ) ); 604 605 // initialize the "lapic_input" structure 606 // defining how internal IRQs are connected to LAPIC 607 uint32_t id; 608 uint8_t valid; 609 uint8_t channel; 610 uint32_t func; 611 612 for( id = 0 ; id < CONFIG_MAX_INTERNAL_IRQS ; id++ ) 613 { 614 valid = dev_tbl[i].irq[id].valid; 615 func = FUNC_FROM_TYPE( dev_tbl[i].irq[id].dev_type ); 616 channel = dev_tbl[i].irq[id].channel; 617 618 if( valid ) // only valid local IRQs are registered 560 619 { 561 valid = dev_tbl[i].irq[id].valid; 562 dev_type = dev_tbl[i].irq[id].dev_type; 563 channel = dev_tbl[i].irq[id].channel; 564 is_rx = dev_tbl[i].irq[id].is_rx; 565 566 if( valid ) // only valid inputs are registered 567 { 568 uint32_t * index; // local pointer on one entry 569 uint16_t dev_func = FUNC_FROM_TYPE( dev_type ); 570 571 if( dev_func == DEV_FUNC_TXT ) 572 { 573 index = &chdev_pic_input.txt[channel]; 574 } 575 else if( dev_func == DEV_FUNC_IOC ) 576 { 577 index = &chdev_pic_input.ioc[channel]; 578 } 579 else if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) ) 580 { 581 index = &chdev_pic_input.nic_tx[channel]; 582 } 583 else if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) ) 584 { 585 index = &chdev_pic_input.nic_rx[channel]; 586 } 587 else 588 { 589 assert( false , __FUNCTION__ , "illegal source device for PIC input" ); 590 } 591 592 // set entry in local structure 593 *index = id; 594 } 595 } // end loop on PIC inputs 596 } // end PIC 597 } // end loop on devices 598 } // end external_devices_init() 599 620 if ( func == DEV_FUNC_MMC ) lapic_input.mmc = id; 621 else if( func == DEV_FUNC_DMA ) lapic_input.dma[channel] = id; 622 else assert( false , __FUNCTION__ , "illegal source device for LAPIC input" ); 623 } 624 } 625 } 626 } // end lapic_init() 600 627 601 628 /////////////////////////////////////////////////////////////////////////////////////////// … … 645 672 void kernel_init( boot_info_t * info ) 646 673 { 647 lid_t core_lid = -1; // running core local index 648 cxy_t core_cxy = -1; // running core cluster identifier 649 gid_t core_gid; // running core hardware identifier 650 cluster_t * cluster; // pointer on local cluster manager 651 core_t * core; // pointer on running core descriptor 652 thread_t * thread; // pointer on idle thread descriptor 674 lid_t core_lid = -1; // running core local index 675 cxy_t core_cxy = -1; // running core cluster identifier 676 gid_t core_gid; // running core hardware identifier 677 cluster_t * cluster; // pointer on local cluster manager 678 core_t * core; // pointer on running core descriptor 679 thread_t * thread; // pointer on idle thread descriptor 680 xptr_t vfs_root_inode_xp; // extended pointer on VFS root inode 681 // xptr_t devfs_root_inode_xp; // extended pointer on DEVFS root inode 653 682 error_t error; 654 683 655 // all cores get and check core identifiers 684 cxy_t io_cxy = info->io_cxy; 685 686 ///////////////////////////////////////////////////////////////////////////////// 687 // STEP 0 : Each core get its core identifier from boot_info, and makes 688 // a partial initialisation of its private idle thread descriptor. 689 // CP0 initializes the "local_cxy" global variable. 690 // CP0 in cluster IO initializes the TXT0 chdev to print log messages. 691 ///////////////////////////////////////////////////////////////////////////////// 692 656 693 error = get_core_identifiers( info, 657 694 &core_lid, … … 668 705 hal_set_current_thread( thread ); 669 706 707 // each core initializes the idle thread "locks_root" and "xlocks_root" fields 670 708 list_root_init( &thread->locks_root ); 671 xlist_root_init( XPTR( local_cxy, &thread->xlocks_root ) ); 672 673 // CP0 in I/O cluster initializes TXT0 chdev descriptor 674 if( (core_lid == 0) && (core_cxy == info->io_cxy) ) txt0_device_init( info ); 675 676 ///////////////////////////////////////////////////////////////////////////////// 677 // global & local synchro to protect access to TXT0 terminal 678 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 709 xlist_root_init( XPTR( local_cxy , &thread->xlocks_root ) ); 710 711 // CP0 in I/O cluster initialises TXT0 chdev descriptor 712 if( (core_lid == 0) && (core_cxy == io_cxy) ) txt0_device_init( info ); 713 714 ///////////////////////////////////////////////////////////////////////////////// 715 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 679 716 (info->x_size * info->y_size) ); 680 717 barrier_wait( &local_barrier , info->cores_nr ); 681 ///////////////////////////////////////////////////////////////////////////////// 682 683 if( (core_lid == 0) && (local_cxy == info->io_cxy) ) 684 { 685 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0 at cycle %d\n", 686 __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() ); 687 } 688 689 // all cores check core identifiers 718 719 if( (core_lid == 0) && (local_cxy == 0) ) 720 kinit_dmsg("\n[INFO] %s exit barrier 0 at cycle %d : TXT0 initialized\n", 721 __FUNCTION__, (uint32_t)hal_time_stamp()); 722 723 ///////////////////////////////////////////////////////////////////////////// 724 // STEP 1 : all cores check its core identifier. 725 // CP0 initializes the local cluster manager. 726 // This includes the memory allocators. 727 ///////////////////////////////////////////////////////////////////////////// 728 729 // all cores check identifiers 690 730 if( error ) 691 731 { … … 696 736 } 697 737 698 // CP0 initializes the local cluster manager (cores and memory allocators)738 // CP0 initializes cluster manager 699 739 if( core_lid == 0 ) 700 740 { … … 703 743 if( error ) 704 744 { 705 nolock_printk("\n[PANIC] in %s : cannot initialise cluster manager in cluster%x",745 nolock_printk("\n[PANIC] in %s : cannot initialise cluster %x", 706 746 __FUNCTION__ , local_cxy ); 707 747 hal_core_sleep(); … … 710 750 711 751 ///////////////////////////////////////////////////////////////////////////////// 712 // global & local synchro, to protect access to cluster manager 713 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 752 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 714 753 (info->x_size * info->y_size) ); 715 754 barrier_wait( &local_barrier , info->cores_nr ); 716 755 ///////////////////////////////////////////////////////////////////////////////// 717 756 718 if( (core_lid == 0) && (local_cxy == info->io_cxy) ) 719 { 720 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 at cycle %d\n", 721 __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() ); 722 } 723 724 // all cores get pointer on local cluster manager and on core descriptor 757 if( (core_lid == 0) && (local_cxy == 0) ) 758 kinit_dmsg("\n[INFO] %s exit barrier 1 at cycle %d : clusters initialised\n", 759 __FUNCTION__, (uint32_t)hal_time_stamp()); 760 761 ///////////////////////////////////////////////////////////////////////////////// 762 // STEP 2 : all CP0s initialize the process_zero descriptor. 763 // CP0 in cluster 0 initialises the IOPIC device. 764 // all CP0s complete the distibuted LAPIC initialization. 765 ///////////////////////////////////////////////////////////////////////////////// 766 767 // all cores get pointer on local cluster manager & core descriptor 725 768 cluster = &cluster_manager; 726 769 core = &cluster->core_tbl[core_lid]; 727 770 728 // CP0 initializesthe process_zero descriptor771 // all CP0s initialize the process_zero descriptor 729 772 if( core_lid == 0 ) process_reference_init( &process_zero , 0 , XPTR_NULL ); 730 773 731 #ifdef __HAL_x86_64__ 732 return; /* XXX temporary */ 733 #endif 734 735 // CP0 allocates and initializes the internal peripheral chdev descriptors. 736 // Each CP0[cxy] scan the set of its internal (private) peripherals, 774 // CP0 in cluster 0 initializes the PIC chdev, 775 if( (core_lid == 0) && (local_cxy == 0) ) iopic_init( info ); 776 777 // all CP0s initialize their local LAPIC extension, 778 if( core_lid == 0 ) lapic_init( info ); 779 780 //////////////////////////////////////////////////////////////////////////////// 781 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 782 (info->x_size * info->y_size) ); 783 barrier_wait( &local_barrier , info->cores_nr ); 784 //////////////////////////////////////////////////////////////////////////////// 785 786 if( (core_lid == 0) && (local_cxy == 0) ) 787 kinit_dmsg("\n[INFO] %s exit barrier 2 at cycle %d : PIC initialised\n", 788 __FUNCTION__, (uint32_t)hal_time_stamp()); 789 790 //////////////////////////////////////////////////////////////////////////////// 791 // STEP 3 : all CP0s initialize their local chdev descriptors 792 // (both internal devices and external devices). 793 //////////////////////////////////////////////////////////////////////////////// 794 795 // CP0 scan the internal (private) peripherals, 737 796 // and allocates memory for the corresponding chdev descriptors. 738 797 if( core_lid == 0 ) internal_devices_init( info ); 739 740 // CP0 allocates one WTI mailbox per core for Inter Processor Interrupt 741 // this must be done after ICU chdev initialisation, by CP0 only, and before 742 // external devices initialisation to enforce the rule : 743 // "The WTI index for the IPI routed to core[lid] is lid" 744 if( core_lid == 1 ) 745 { 746 uint32_t wti_id; 747 uint32_t lid; 748 for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ ) 749 { 750 wti_id = dev_icu_wti_alloc(); 751 752 if( wti_id != lid ) 753 { 754 nolock_printk("\n[PANIC] in %s : WTI index for IPI = %d / core_lid = %d", 755 __FUNCTION__ , wti_id , lid ); 756 hal_core_sleep(); 757 } 758 759 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , NULL ); 760 } 761 } 798 762 799 763 800 // All CP0s contribute to initialise external peripheral chdev descriptors. … … 765 802 // and allocates memory for the chdev descriptors that must be placed 766 803 // on the (cxy) cluster according to the global index value. 804 767 805 if( core_lid == 0 ) external_devices_init( info ); 768 806 769 807 ///////////////////////////////////////////////////////////////////////////////// 770 // global &local synchro to protect access to peripherals 771 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 808 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 772 809 (info->x_size * info->y_size) ); 773 810 barrier_wait( &local_barrier , info->cores_nr ); 774 811 ///////////////////////////////////////////////////////////////////////////////// 775 812 776 if( (core_lid == 0) && (local_cxy == info->io_cxy) ) 777 { 778 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 at cycle %d\n", 779 __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() ); 780 } 781 813 if( (core_lid == 0) && (local_cxy == 0) ) 814 kinit_dmsg("\n[INFO] %s exit barrier 3 at cycle %d : all chdev initialised\n", 815 __FUNCTION__, (uint32_t)hal_time_stamp()); 816 817 ///////////////////////////////////////////////////////////////////////////////// 818 // STEP 4 : Alls cores initialize their private IDLE thread. 819 // Only CP0 in cluster 0 creates the VFS root inode. 820 // It access the boot device to initialize the file system context. 821 ///////////////////////////////////////////////////////////////////////////////// 822 823 // all cores create idle thread descriptor 782 824 error = thread_kernel_init( thread, 783 825 THREAD_IDLE, … … 792 834 } 793 835 794 // register idle thread in scheduler836 // all cores register idle thread in scheduler 795 837 core->scheduler.idle = thread; 796 838 797 // a ctivate the idle thread839 // all core activate the idle thread 798 840 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL ); 799 841 800 if( (core_lid == 0) && (local_cxy == info->io_cxy) ) 801 { 802 kinit_dmsg("\n[INFO] %s : core[%x][%d] created idle thread %x at cycle %d\n", 803 __FUNCTION__ , core_cxy , core_lid , thread , hal_get_cycles()); 804 } 805 806 // CP0 in all clusters initializes cooperatively VFS and DEVFS 807 if( (core_lid == 0) ) 808 { 809 xptr_t root_inode_xp; 810 811 // initialize root File System (must be FATFS in this implementation) 842 if( (core_lid == 0) && (local_cxy == 0) ) 843 { 844 kinit_dmsg("\n[INFO] %s : created idle thread %x at cycle %d\n", 845 __FUNCTION__ , thread , (uint32_t)hal_time_stamp()); 846 } 847 848 // CPO in cluster 0 creates the VFS root 849 if( (core_lid == 0) && (local_cxy == 0 ) ) 850 { 851 vfs_root_inode_xp = XPTR_NULL; 852 853 // File System must be FATFS in this implementation, 854 // but other File System can be introduced here 812 855 if( CONFIG_VFS_ROOT_IS_FATFS ) 813 856 { 814 root_inode_xp = fatfs_init(); 857 // 1. create FATFS context in cluster 0 858 fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc(); 859 860 nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ , 861 "cannot create FATFS context in cluster 0\n" ); 862 863 // 2. access boot device to initialize FATFS context 864 fatfs_ctx_init( fatfs_ctx ); 865 866 // 3. get various informations from FATFS context 867 uint32_t root_dir_cluster = fatfs_ctx->root_dir_cluster; 868 uint32_t cluster_size = fatfs_ctx->bytes_per_sector * 869 fatfs_ctx->sectors_per_cluster; 870 uint32_t total_clusters = fatfs_ctx->fat_sectors_count << 7; 871 872 // 4. create VFS root inode in cluster 0 873 error = vfs_inode_create( XPTR_NULL, // dentry_xp 874 FS_TYPE_FATFS, // fs_type 875 INODE_TYPE_DIR, // inode_type 876 (void *)(intptr_t)root_dir_cluster, // extend 877 0, // attr 878 0, // rights 879 0, // uid 880 0, // gid 881 &vfs_root_inode_xp ); // return 882 883 nolock_assert( (error == 0) , __FUNCTION__ , 884 "cannot create VFS root inode\n" ); 885 886 // 5. initialize VFS context for FAT in cluster 0 887 vfs_ctx_init( FS_TYPE_FATFS, // file system type 888 0, // attributes 889 total_clusters, 890 cluster_size, 891 vfs_root_inode_xp, // VFS root 892 fatfs_ctx ); // extend 815 893 } 816 894 else … … 820 898 } 821 899 822 if( root_inode_xp == XPTR_NULL )823 {824 nolock_printk("\n[PANIC] in %s : core[%x][%d] cannot initialize file system\n",825 __FUNCTION__ , local_cxy , core_lid );826 hal_core_sleep();827 }828 829 900 // register VFS root inode in process_zero 830 process_zero.vfs_root_xp = root_inode_xp; 831 process_zero.vfs_cwd_xp = root_inode_xp; 832 833 // mount the DEVFS File system 834 devfs_mount( root_inode_xp , "dev" ); 835 } 836 837 838 // CP0 in I/O cluster creates the process_init and print banner 839 if( (core_lid == 0) && (local_cxy == info->io_cxy) ) 901 process_zero.vfs_root_xp = vfs_root_inode_xp; 902 process_zero.vfs_cwd_xp = vfs_root_inode_xp; 903 } 904 905 ///////////////////////////////////////////////////////////////////////////////// 906 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 907 (info->x_size * info->y_size) ); 908 barrier_wait( &local_barrier , info->cores_nr ); 909 ///////////////////////////////////////////////////////////////////////////////// 910 911 if( (core_lid == 0) && (local_cxy == 0) ) 912 kinit_dmsg("\n[INFO] %s exit barrier 4 at cycle %d : VFS OK in cluster 0\n", 913 __FUNCTION__, (uint32_t)hal_time_stamp()); 914 915 ///////////////////////////////////////////////////////////////////////////////// 916 // STEP 5 : Other CP0s allocate memory for the selected FS context, 917 // and initialise both the local FS context and the local VFS context 918 // from values stored in cluster 0. 919 // They get the VFS root inode extended pointer from cluster 0. 920 ///////////////////////////////////////////////////////////////////////////////// 921 922 if( (core_lid == 0) && (local_cxy != 0) ) 923 { 924 // File System must be FATFS in this implementation, 925 // but other File System can be introduced here 926 if( CONFIG_VFS_ROOT_IS_FATFS ) 927 { 928 // allocate memory for FATFS context 929 fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc(); 930 931 nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ , 932 "cannot create FATFS context\n" ); 933 934 // get local pointer on VFS context for FATFS 935 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 936 937 // copy VFS context from cluster 0 to local cluster 938 hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 939 XPTR( 0 , vfs_ctx ), 940 sizeof(vfs_ctx_t) ); 941 942 // copy FATFS context from cluster 0 to local cluster 943 hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ), 944 XPTR( 0 , fatfs_ctx ), 945 sizeof(fatfs_ctx_t) ); 946 947 // update extend field in local copy of VFS context 948 vfs_ctx->extend = fatfs_ctx; 949 } 950 951 // get extended pointer on VFS root inode from cluster 0 952 vfs_root_inode_xp = hal_remote_lwd( XPTR( 0 , process_zero.vfs_root_xp ) ); 953 954 // update local process_zero descriptor 955 process_zero.vfs_root_xp = vfs_root_inode_xp; 956 process_zero.vfs_cwd_xp = vfs_root_inode_xp; 957 } 958 959 ///////////////////////////////////////////////////////////////////////////////// 960 // global &local synchro to protect File System initialisation 961 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 962 (info->x_size * info->y_size) ); 963 barrier_wait( &local_barrier , info->cores_nr ); 964 965 if( (core_lid == 0) && (local_cxy == 0) ) 966 kinit_dmsg("\n[INFO] %s exit barrier 5 at cycle %d : VFS OK in all clusters\n", 967 __FUNCTION__, (uint32_t)hal_time_stamp()); 968 969 970 ///////////////////////////////////////////////////////////////////////////////// 971 // STEP 6 : CP0 in cluster IO makes the global DEVFS tree initialisation: 972 // It creates the DEVFS root directory and the DEVFS "external" 973 // diretory in cluster IO and mount these inodes into VFS. 974 ///////////////////////////////////////////////////////////////////////////////// 975 976 if( (core_lid == 0) && (local_cxy == io_cxy) ) 977 { 978 xptr_t devfs_root_inode_xp; // extended pointer on DEVFS root directory 979 xptr_t devfs_external_inode_xp; // extended pointer on DEVFS external directory 980 981 // create "dev" and "external" directories. 982 devfs_global_init( process_zero.vfs_root_xp, 983 &devfs_root_inode_xp, 984 &devfs_external_inode_xp ); 985 986 // creates the DEVFS context in cluster IO 987 devfs_ctx_t * devfs_ctx = devfs_ctx_alloc(); 988 989 nolock_assert( (devfs_ctx != NULL) , __FUNCTION__ , 990 "cannot create DEVFS context in cluster IO\n"); 991 992 // register DEVFS root and external directories 993 devfs_ctx_init( devfs_ctx, devfs_root_inode_xp, devfs_external_inode_xp ); 994 } 995 996 ///////////////////////////////////////////////////////////////////////////////// 997 // global &local synchro to protect File System initialisation 998 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 999 (info->x_size * info->y_size) ); 1000 barrier_wait( &local_barrier , info->cores_nr ); 1001 1002 if( (core_lid == 0) && (local_cxy == 0) ) 1003 kinit_dmsg("\n[INFO] %s exit barrier 6 at cycle %d : DEVFS OK in cluster IO\n", 1004 __FUNCTION__, (uint32_t)hal_time_stamp()); 1005 1006 ///////////////////////////////////////////////////////////////////////////////// 1007 // STEP 7 : All CP0s complete in parallel the DEVFS tree initialization. 1008 // Each CP0 get the "dev" and "external" extended pointers from 1009 // values storred in cluster IO. Then CP0 in cluster(i) creates the 1010 // DEVFS "internal directory, and creates the pseudo-files for all 1011 // chdevs contained in cluster (i). 1012 ///////////////////////////////////////////////////////////////////////////////// 1013 1014 if( core_lid == 0 ) 1015 { 1016 xptr_t root_inode_xp; // extended pointer on DEVFS root directory 1017 xptr_t external_inode_xp; // extended pointer on DEVFS external directory 1018 1019 // get extended pointer on "extend" field of VFS context for DEVFS in cluster IO 1020 xptr_t extend_xp = XPTR( io_cxy , &fs_context[FS_TYPE_DEVFS].extend ); 1021 1022 // get pointer on DEVFS context in cluster IO 1023 devfs_ctx_t * devfs_ctx = hal_remote_lpt( extend_xp ); 1024 1025 root_inode_xp = hal_remote_lwd( XPTR( io_cxy , &devfs_ctx->root_inode_xp ) ); 1026 external_inode_xp = hal_remote_lwd( XPTR( io_cxy , &devfs_ctx->external_inode_xp ) ); 1027 1028 devfs_local_init( root_inode_xp, 1029 external_inode_xp ); 1030 } 1031 1032 ///////////////////////////////////////////////////////////////////////////////// 1033 // global &local synchro to protect File System initialisation 1034 if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ), 1035 (info->x_size * info->y_size) ); 1036 barrier_wait( &local_barrier , info->cores_nr ); 1037 1038 if( (core_lid == 0) && (local_cxy == 0) ) 1039 kinit_dmsg("\n[INFO] %s exit barrier 7 at cycle %d : DEVFS OK in all clusters\n", 1040 __FUNCTION__, (uint32_t)hal_time_stamp()); 1041 1042 ///////////////////////////////////////////////////////////////////////////////// 1043 // STEP 8 : CP0 in I/O cluster creates the process_init and print banner. 1044 ///////////////////////////////////////////////////////////////////////////////// 1045 1046 if( (core_lid == 0) && (local_cxy == io_cxy) ) 840 1047 { 841 1048 process_init_create(); 842 1049 } 1050 1051 ///////////////////////////////////////////////////////////////////////////////// 1052 // global syncho to protect access to File System 1053 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 1054 (info->x_size * info->y_size) ); 1055 barrier_wait( &local_barrier , info->cores_nr ); 1056 1057 if( (core_lid == 0) && (local_cxy == 0) ) 1058 kinit_dmsg("\n[INFO] %s exit barrier 8 at cycle %d : process init created\n", 1059 __FUNCTION__ , (uint32_t)hal_time_stamp() ); 1060 1061 ///////////////////////////////////////////////////////////////////////////////// 1062 // STEP 9 : CP0 in cluster 0 print banner 1063 ///////////////////////////////////////////////////////////////////////////////// 1064 1065 if( (core_lid == 0) && (local_cxy == io_cxy) ) 1066 { 843 1067 print_banner( (info->x_size * info->y_size) , info->cores_nr ); 844 1068 … … 886 1110 } 887 1111 888 /////////////////////////////////////////////////////////////////////////////////889 // global syncho to protect access to File System890 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),891 (info->x_size * info->y_size) );892 barrier_wait( &local_barrier , info->cores_nr );893 /////////////////////////////////////////////////////////////////////////////////894 895 if( (core_lid == 0) && (local_cxy == info->io_cxy) )896 {897 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 at cycle %d\n",898 __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() );899 }900 901 1112 // each core activates its private PTI IRQ 902 dev_icu_set_period( core_lid , CONFIG_SCHED_TICK_PERIOD ); 903 dev_icu_enable_irq( core_lid , PTI_TYPE , core_lid , NULL ); 904 905 // each core get its private IRQ masks values 906 uint32_t hwi_mask; 907 uint32_t wti_mask; 908 uint32_t pti_mask; 909 dev_icu_get_masks( core_lid , &hwi_mask , &wti_mask , &pti_mask ); 910 911 thread_dmsg("\n[INFO] %s : core[%x][%d] complete kernel init at cycle %d\n" 912 " hwi_mask = %x / wti_mask = %x / pti_mask = %x\n", 913 __FUNCTION__ , local_cxy , core_lid , hal_get_cycles() , 914 hwi_mask , wti_mask , pti_mask ); 1113 dev_pic_enable_timer( CONFIG_SCHED_TICK_PERIOD ); 1114 1115 if( (core_lid == 0) && (local_cxy == io_cxy) ) 1116 thread_dmsg("\n[INFO] %s complete kernel init in cluster 0 at cycle %d\n" 1117 __FUNCTION__ , (uint32_t)hal_time_stamp() ) 915 1118 916 1119 // each core jump to idle thread -
trunk/kernel/kern/printk.c
r103 r188 35 35 /////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern chdev_ t txt0_chdev; // allocated in kernel_init.c37 extern chdev_directory_t chdev_dir; // defined in chdev.h / allocated in kernel_init.c 38 38 39 39 ///////////////////////////////////// … … 369 369 uint32_t save_sr; 370 370 371 // get pointers on TXT0 chdev 372 xptr_t txt0_xp = chdev_dir.txt[0]; 373 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 374 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 375 371 376 // get extended pointer on remote TXT0 chdev lock 372 xptr_t txt0_lock_xp = XPTR( LOCAL_CLUSTER->io_cxy , &txt0_chdev.wait_lock );377 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 373 378 374 379 // get TXT0 lock in busy waiting mode 375 remote_spinlock_lock_busy( txt0_lock_xp , &save_sr );380 remote_spinlock_lock_busy( lock_xp , &save_sr ); 376 381 377 382 // call kernel_printf on TXT0, in busy waiting mode … … 381 386 382 387 // release lock 383 remote_spinlock_unlock_busy( txt0_lock_xp , save_sr );388 remote_spinlock_unlock_busy( lock_xp , save_sr ); 384 389 } 385 390 … … 406 411 } 407 412 } 413 414 ////////////////////////////////////////////////// 415 inline void nolock_assert( bool_t condition, 416 const char * function_name, 417 char * string ) 418 { 419 if( condition == false ) 420 { 421 nolock_printk("\n[PANIC] in %s : %s\n" , function_name , string ); 422 hal_core_sleep(); 423 } 424 } 425 408 426 409 427 -
trunk/kernel/kern/printk.h
r103 r188 83 83 84 84 /********************************************************************************** 85 * This function display a "PANIC" message and force the calling core in85 * This function displays a "PANIC" message and force the calling core in 86 86 * sleeping mode if a Boolean condition is false. 87 87 * These functions are actually used to debug the kernel... … … 95 95 char * string ); 96 96 97 /********************************************************************************** 98 * This function displays a "PANIC" message and force the calling core in 99 * sleeping mode if a Boolean condition is false, 100 * without taking the the lock protecting exclusive access to TXT0 terminal. 101 ********************************************************************************** 102 * @ condition : condition that must be true. 103 * @ function_name : name of the calling function. 104 * @ string : error message if condition is false. 105 *********************************************************************************/ 106 inline void nolock_assert( bool_t condition, 107 const char * function_name, 108 char * string ); 109 97 110 /////////////////////////////////////////////////////////////////////////////////// 98 111 // Conditionnal debug macros … … 171 184 #endif 172 185 173 #if CONFIG_ICU_DEBUG174 #define icu_dmsg(...) printk(__VA_ARGS__)175 #else176 #define icu_dmsg(...)177 #endif178 179 186 #if CONFIG_IDLE_DEBUG 180 187 #define idle_dmsg(...) printk(__VA_ARGS__) … … 187 194 #else 188 195 #define ioc_dmsg(...) 196 #endif 197 198 #if CONFIG_IRQ_DEBUG 199 #define irq_dmsg(...) printk(__VA_ARGS__) 200 #else 201 #define irq_dmsg(...) 189 202 #endif 190 203 -
trunk/kernel/kern/process.c
r186 r188 99 99 assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n"); 100 100 101 parent_pid = 0; // process_zero is its own parent... 101 parent_cxy = 0; 102 parent_ptr = NULL; 103 parent_pid = 0; // process_zero is its own parent... 102 104 } 103 105 else -
trunk/kernel/kern/rpc.c
r101 r188 537 537 uint32_t fs_type, // in 538 538 uint32_t inode_type, // in 539 void * extend, // in 539 540 uint32_t attr, // in 540 541 uint32_t rights, // in … … 560 561 rpc.args[1] = (uint64_t)fs_type; 561 562 rpc.args[2] = (uint64_t)inode_type; 562 rpc.args[3] = (uint64_t)attr; 563 rpc.args[4] = (uint64_t)rights; 564 rpc.args[5] = (uint64_t)uid; 565 rpc.args[6] = (uint64_t)gid; 563 rpc.args[3] = (uint64_t)(intptr_t)extend; 564 rpc.args[4] = (uint64_t)attr; 565 rpc.args[5] = (uint64_t)rights; 566 rpc.args[6] = (uint64_t)uid; 567 rpc.args[7] = (uint64_t)gid; 566 568 567 569 // register RPC request in remote RPC fifo (blocking function) … … 569 571 570 572 // get output values from RPC descriptor 571 *inode_xp = (xptr_t)rpc.args[ 7];572 *error = (error_t)rpc.args[ 8];573 *inode_xp = (xptr_t)rpc.args[8]; 574 *error = (error_t)rpc.args[9]; 573 575 } 574 576 … … 579 581 uint32_t fs_type; 580 582 uint32_t inode_type; 583 void * extend; 581 584 uint32_t attr; 582 585 uint32_t rights; … … 591 594 592 595 // get input arguments from client rpc descriptor 593 dentry_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 594 fs_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 595 inode_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 596 attr = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 597 rights = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); 598 uid = (uid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); 599 gid = (gid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) ); 596 dentry_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 597 fs_type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 598 inode_type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 599 extend = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 600 attr = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); 601 rights = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); 602 uid = (uid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) ); 603 gid = (gid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[7] ) ); 600 604 601 605 // call local kernel function … … 603 607 fs_type, 604 608 inode_type, 609 extend, 605 610 attr, 606 611 rights, … … 610 615 611 616 // set output arguments 612 hal_remote_swd( XPTR( client_cxy , &desc->args[ 7] ) , (uint64_t)inode_xp );613 hal_remote_swd( XPTR( client_cxy , &desc->args[ 8] ) , (uint64_t)error );617 hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)inode_xp ); 618 hal_remote_swd( XPTR( client_cxy , &desc->args[9] ) , (uint64_t)error ); 614 619 } 615 620 … … 1290 1295 if( cores == 0 ) // no core in kernel mode in server 1291 1296 { 1292 dev_ icu_send_ipi( server_cxy , client_lid );1297 dev_pic_send_ipi( server_cxy , client_lid ); 1293 1298 1294 1299 rpc_dmsg("\n[INFO] %s : core %d in cluster %x send IPI to core %d in cluster %x\n", … … 1454 1459 1455 1460 // update core descriptor counter 1456 core->rpc_threads++;1461 hal_atomic_add( &core->rpc_threads , 1 ); 1457 1462 } 1458 1463 … … 1549 1554 1550 1555 // update core descriptor counter 1551 this->core->rpc_threads--;1556 hal_atomic_add( &this->core->rpc_threads , -1 ); 1552 1557 1553 1558 // suicide -
trunk/kernel/kern/rpc.h
r23 r188 325 325 * @ fs_type : [in] file system type. 326 326 * @ inode_type : [in] file system type. 327 * @ extend : [in] fs_type_specific inode extension. 327 328 * @ attr : [in] inode attributes. 328 329 * @ rights : [in] access rights … … 336 337 uint32_t fs_type, 337 338 uint32_t inode_type, 339 void * extend, 338 340 uint32_t attr, 339 341 uint32_t rights, -
trunk/kernel/kern/thread.c
r185 r188 34 34 #include <process.h> 35 35 #include <scheduler.h> 36 #include <dev_ icu.h>36 #include <dev_pic.h> 37 37 #include <core.h> 38 38 #include <list.h> … … 718 718 thread_block( target , THREAD_BLOCKED_GLOBAL ); 719 719 720 // send an IPI to reschedule the target thread core.721 dev_ icu_send_ipi( local_cxy , target->core->lid );720 // send an IPI to schedule the target thread core. 721 dev_pic_send_ipi( local_cxy , target->core->lid ); 722 722 } 723 723 … … 739 739 idle_dmsg("\n[INFO] %s : core[%x][%d] wake up at cycle %d\n", 740 740 __FUNCTION__ , local_cxy , lid , hal_get_cycles() ); 741 742 // acknowledge IRQ743 dev_icu_irq_handler();744 741 745 742 // force scheduling -
trunk/kernel/libk/xhtab.c
r50 r188 35 35 36 36 /////////////////////////////////////////////////////////////////////////////////////////// 37 // Item type specific (static) functions (twofunctions for each item type).38 // - for type <vfs_dentry_t>, identifier is the name field.39 /////////////////////////////////////////////////////////////////////////////////////////// 40 41 // /////////////////////////////////////////////////////////////////////////////////////////42 // The se static functions compute the hash index from the key.43 /////////////////////////////////////////////////////////////////////////////////////////// 44 // @ key : local pointer on key.37 // Item type specific functions (three functions for each item type). 38 /////////////////////////////////////////////////////////////////////////////////////////// 39 40 /////////////////////////////////////////////////////////////////////////////////////////// 41 // This functions compute the hash index from the key when item is a vfs_dentry_t. 42 // The key is the directory entry name. 43 /////////////////////////////////////////////////////////////////////////////////////////// 44 // @ key : local pointer on name. 45 45 // @ return the index value, from 0 to (HASHTAB_SIZE - 1) 46 46 /////////////////////////////////////////////////////////////////////////////////////////// 47 48 ///////////////////////////////////////// 49 uint32_t xhtab_dentry_index( void * key ) 47 static uint32_t xhtab_dentry_index_from_key( void * key ) 50 48 { 51 49 char * name = key; … … 55 53 index = index + (*(name++) ^ index); 56 54 } 57 return index % HASHTAB_SIZE;55 return index % XHASHTAB_SIZE; 58 56 } 59 57 58 /////////////////////////////////////////////////////////////////////////////////////////// 59 // This functions returns the extended pointer on the item, from the extended pointer 60 // on xlist contained in the item, when the item is a vfs_entry_t. 61 /////////////////////////////////////////////////////////////////////////////////////////// 62 // @ xlist_xp : extended pointer on embedded xlist entry. 63 // @ return the extended pointer on the dentry containing this xlist entry. 64 /////////////////////////////////////////////////////////////////////////////////////////// 65 static xptr_t xhtab_dentry_item_from_xlist( xptr_t xlist_xp ) 66 { 67 return XLIST_ELEMENT( xlist_xp , vfs_dentry_t , list ); 68 } 69 60 70 //////////////////////////////////////////////////////////////////////////////////////////// 61 // These static function are used by xhtab_lookup(), xhtab_insert(), xhtab_remove(). 62 // They scan one sub-list identified by <index> to find an item identified by <key>. 63 // The sub-list is not modified, but the readlock must have been taken by the caller. 71 // This function compare the identifier of an item to a given <key>. For a vfs_entry_t, 72 // it returns true when the directory name matches the name pointed by the <key> argument. 64 73 //////////////////////////////////////////////////////////////////////////////////////////// 65 // @ xhtab_xp : extended pointer on hash table. 66 // @ index : index of sub-list to be scanned. 67 // @ key : local pointer on item identifier. 68 // return an extended pointer on item if found / return XPTR_NULL if not found. 74 // @ item_xp : extended pointer on item. 75 // @ key : pointer on searched item identifier. 76 // returns true if given name matches directory entry name. 69 77 //////////////////////////////////////////////////////////////////////////////////////////// 70 71 //////////////////////////////////////////////////// 72 static xptr_t xhtab_dentry_scan( xptr_t xhtab_xp, 73 uint32_t index, 74 void * key ) 78 static bool_t xhtab_dentry_item_match_key( xptr_t item_xp, 79 void * key ) 80 { 81 vfs_dentry_t * dentry_ptr; 82 cxy_t dentry_cxy; 83 84 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 85 86 // get dentry cluster and local pointer 87 dentry_cxy = GET_CXY( item_xp ); 88 dentry_ptr = (vfs_dentry_t *)GET_PTR( item_xp ); 89 90 // make a local copy of directory entry name 91 hal_remote_strcpy( XPTR( local_cxy , name ) , 92 XPTR( dentry_cxy , &dentry_ptr->name ) ); 93 94 return( strcmp( name , (char*)key ) == 0 ); 95 } 96 97 //////////////////////////////////////////////////////////////////////////////////////// 98 // Generic access functions 99 //////////////////////////////////////////////////////////////////////////////////////// 100 101 ////////////////////////////////////////// 102 void xhtab_init( xhtab_t * xhtab, 103 xhtab_item_type_t type ) 104 { 105 uint32_t i; 106 107 // initialize readlock 108 remote_rwlock_init( XPTR( local_cxy , &xhtab->lock) ); 109 110 xhtab->items = 0; 111 112 if( type == XHTAB_DENTRY_TYPE ) 113 { 114 xhtab->item_match_key = &xhtab_dentry_item_match_key; 115 xhtab->index_from_key = &xhtab_dentry_index_from_key; 116 xhtab->item_from_xlist = &xhtab_dentry_item_from_xlist; 117 } 118 else 119 { 120 printk("\n[PANIC] in %s : illegal item type\n", __FUNCTION__ ); 121 hal_core_sleep(); 122 } 123 124 for( i=0 ; i < XHASHTAB_SIZE ; i++ ) 125 { 126 xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) ); 127 } 128 129 } // end xhtab_init() 130 131 ////////////////////////////////////// 132 xptr_t xhtab_scan( xptr_t xhtab_xp, 133 uint32_t index, 134 void * key ) 75 135 { 76 136 xptr_t xlist_xp; // xlist_entry_t (iterator) 137 xptr_t item_xp; // associated item 77 138 xhtab_t * xhtab_ptr; // hash table local pointer 78 139 cxy_t xhtab_cxy; // hash table cluster 79 char local_name[CONFIG_VFS_MAX_NAME_LENGTH]; // local copy of dentry name80 140 81 141 // get hash table cluster and local pointer … … 86 146 XLIST_FOREACH( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ) 87 147 { 88 // get extended pointer on dentry containing the xlist_entry_t 89 xptr_t dentry_xp = XLIST_ELEMENT( xlist_xp , vfs_dentry_t , xlist ); 90 91 // get dentry cluster and local pointer 92 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 93 vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp ); 94 95 // make a local copy of dentry name 96 hal_remote_memcpy( XPTR( local_cxy , local_name ) , 97 XPTR( dentry_cxy , dentry_ptr->name ), 98 CONFIG_VFS_MAX_NAME_LENGTH ); 99 100 // check matching 101 if( strcmp( local_name , (char *)key ) == 0 ) return dentry_xp; 148 // get extended pointer on item containing the xlist entry 149 item_xp = xhtab_ptr->item_from_xlist( xlist_xp ); 150 151 // check matching 152 if( xhtab_ptr->item_match_key( item_xp , key ) ) return item_xp; 102 153 } 103 154 104 155 // No matching item found 105 156 return XPTR_NULL; 106 }107 108 ////////////////////////////////////////////////////////////////////////////////////////109 // Generic access functions110 ////////////////////////////////////////////////////////////////////////////////////////111 112 //////////////////////////////////////////113 void xhtab_init( xhtab_t * xhtab,114 xhtab_item_type_t type )115 {116 uint32_t i;117 118 // initialize readlock119 remote_rwlock_init( XPTR( local_cxy , &xhtab->lock) );120 121 xhtab->items = 0;122 123 if( type == XHTAB_DENTRY_TYPE )124 {125 xhtab->scan = &xhtab_dentry_scan;126 xhtab->index = &xhtab_dentry_index;127 }128 else129 {130 printk("\n[PANIC] in %s : illegal item type\n", __FUNCTION__ );131 hal_core_sleep();132 }133 134 for( i=0 ; i < HASHTAB_SIZE ; i++ )135 {136 xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );137 }138 157 } 139 158 … … 148 167 149 168 // compute index from key 150 uint32_t index = xhtab_ptr->index ( key );169 uint32_t index = xhtab_ptr->index_from_key( key ); 151 170 152 171 // take the lock protecting hash table … … 154 173 155 174 // search a matching item 156 xptr_t item_xp = xhtab_ ptr->scan( xhtab_xp , index , key );175 xptr_t item_xp = xhtab_scan( xhtab_xp , index , key ); 157 176 158 177 if( item_xp != XPTR_NULL ) // error if found … … 188 207 189 208 // compute index from key 190 uint32_t index = xhtab_ptr->index ( key );209 uint32_t index = xhtab_ptr->index_from_key( key ); 191 210 192 211 // take the lock protecting hash table … … 194 213 195 214 // get extended pointer on item to remove 196 xptr_t item_xp = xhtab_ ptr->scan( xhtab_xp , index , key );215 xptr_t item_xp = xhtab_scan( xhtab_xp , index , key ); 197 216 198 217 if( item_xp == XPTR_NULL ) // error if not found … … 229 248 230 249 // compute index from key 231 uint32_t index = xhtab_ptr->index ( key );250 uint32_t index = xhtab_ptr->index_from_key( key ); 232 251 233 252 // take the lock protecting hash table … … 235 254 236 255 // scan sub-list 237 item_xp = xhtab_ ptr->scan( xhtab_xp , index , key );256 item_xp = xhtab_scan( xhtab_xp , index , key ); 238 257 239 258 // release the lock protecting hash table … … 244 263 } // end xhtab_lookup() 245 264 246 265 /////////////////////////////////////// 266 void xhtab_read_lock( xptr_t xhtab_xp ) 267 { 268 // get xhtab cluster and local pointer 269 cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); 270 xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 271 272 // take the lock protecting hash table 273 remote_rwlock_rd_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 274 } 275 276 ///////////////////////////////////////// 277 void xhtab_read_unlock( xptr_t xhtab_xp ) 278 { 279 // get xhtab cluster and local pointer 280 cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); 281 xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 282 283 // release the lock protecting hash table 284 remote_rwlock_rd_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 285 } 286 287 ///////////////////////////////////////// 288 xptr_t xhtab_get_first( xptr_t xhtab_xp ) 289 { 290 uint32_t index; 291 xptr_t xlist_xp; 292 xptr_t item_xp; 293 xptr_t root_xp; 294 295 // get xhtab cluster and local pointer 296 cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); 297 xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 298 299 //loop on subsets 300 for( index = 0 ; index < XHASHTAB_SIZE ; index++ ) 301 { 302 // get root of subset 303 root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ); 304 305 // get first item 306 xlist_xp = xlist_next( root_xp , root_xp ); 307 308 if( xlist_xp != XPTR_NULL ) // first item found 309 { 310 // get extended pointer on item containing the xlist entry 311 item_xp = xhtab_ptr->item_from_xlist( xlist_xp ); 312 313 // register item in hash table header 314 hal_remote_sw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index ); 315 hal_remote_swd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp ); 316 317 return item_xp; 318 } 319 } 320 321 // item not found 322 return XPTR_NULL; 323 324 } // end xhtab_get_first() 325 326 //////////////////////////////////////// 327 xptr_t xhtab_get_next( xptr_t xhtab_xp ) 328 { 329 uint32_t index; 330 xptr_t xlist_xp; 331 xptr_t item_xp; 332 xptr_t root_xp; 333 334 uint32_t current_index; 335 xptr_t current_xlist_xp; 336 337 // get xhtab cluster and local pointer 338 cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); 339 xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 340 341 // get current item pointers 342 current_index = hal_remote_lw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) ); 343 current_xlist_xp = hal_remote_lwd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) ); 344 345 //loop on subsets 346 for( index = current_index ; index < XHASHTAB_SIZE ; index++ ) 347 { 348 // get root of subset 349 root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ); 350 351 // get next item 352 xlist_xp = xlist_next( root_xp , current_xlist_xp ); 353 354 if( xlist_xp != XPTR_NULL ) // next item found 355 { 356 // get extended pointer on item containing the xlist entry 357 item_xp = xhtab_ptr->item_from_xlist( xlist_xp ); 358 359 // register item in hash table header 360 hal_remote_sw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index ); 361 hal_remote_swd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp ); 362 363 return item_xp; 364 } 365 } 366 367 // item not found 368 return XPTR_NULL; 369 370 } // end xhtab_get_next() 371 372 -
trunk/kernel/libk/xhtab.h
r23 r188 38 38 // The main goal is to speedup search by key for a large number of items of same type. 39 39 // For this purpose the set of all registered items is split in several subsets. 40 // Each subset is organised an embedded double linked lists. 41 // - an item is uniquely identified by a <key>, that can be a single uint32_t, 42 // a name (character string), or a more complex structure. 43 // - From the pointer on <key>, we use an item type specific xhtab_index() function, 40 // Each subset is organised as an embedded double linked lists. 41 // - an item is uniquely identified by a <key>, that is a single uint32_t value. 42 // - From the <key> value,the hash table uses an item type specific xhtab_index() function, 44 43 // to compute an <index> value, defining a subset of registered items. 45 // - to discriminate between items that have the same <index>, the hash table uses another46 // item type specific "xhtab_scan()" function for theassociative search in subset.44 // - to discriminate between items that have the same <index>, the hash table makes 45 // an associative search in subset. 47 46 // - Each registered item is a structure, that must contain an embedded xlist_entry, 48 47 // that is part of the xlist implementing the subset. 49 48 // 50 // Implementation Note: for each supported item type ***, you must define the two 51 // xhtab_***_index() and xhtab_***_scan() functions, and 52 // update the xhtab_init() function. 49 // A total order is defined for all registered items by the increasing index values, 50 // and for each index value by the position in the partial xlist. 51 // This order is used by the two functions xhtab_get_first() and xhtab_get_next(), that 52 // are used to scan all registered items. The two "current_index" and "current_xlist_xp" 53 // fields in the hash table header register the current item during a scan. 54 // 55 // Implementation Note: 56 // For each supported item type ***, you must define the three item-type-specific 57 // functions specified below, and you must update the xhtab_init() function 58 // and the xhtab_item_type_t. 53 59 /////////////////////////////////////////////////////////////////////////////////////////// 54 60 55 #define HASHTAB_SIZE 64 // number of subsets61 #define XHASHTAB_SIZE 64 // number of subsets 56 62 57 63 /****************************************************************************************** 58 * Th ese typedef define the twoitem type specific function prototypes.64 * This define the three item type specific function prototypes. 59 65 *****************************************************************************************/ 60 66 61 typedef xptr_t xhtab_scan_t( xptr_t xhtab_xp , uint32_t index, void * key );62 63 typedef uint32_t xhtab_index_t ( void * key );67 typedef bool_t xhtab_match_t ( xptr_t item_xp , void * key ); 68 typedef xptr_t xhtab_item_t ( xptr_t xlist_xp ); 69 typedef uint32_t xhtab_index_t ( void * key ); 64 70 65 71 /****************************************************************************************** … … 79 85 typedef struct xhtab_s 80 86 { 81 xlist_entry_t roots[HASHTAB_SIZE]; /*! array of roots of xlist */ 82 xhtab_index_t * index; /*! item specific function */ 83 xhtab_scan_t * scan; /*! item specific function */ 87 xlist_entry_t roots[XHASHTAB_SIZE]; /*! array of roots of xlist */ 88 xhtab_index_t * index_from_key; /*! item specific function */ 89 xhtab_match_t * item_match_key; /*! item specific function */ 90 xhtab_item_t * item_from_xlist; /*! item specific function */ 84 91 uint32_t items; /*! number of registered items */ 85 92 remote_rwlock_t lock; /*! lock protecting hash table accesses */ 93 uint32_t current_index; /*! current item subset index */ 94 xptr_t * current_xlist_xp; /*! xptr on current item xlist entry */ 86 95 } 87 96 xhtab_t; … … 131 140 void * key ); 132 141 142 /****************************************************************************************** 143 * This blocking function takes the lock protecting exclusive access to the hash table. 144 * It should be called before the xhtab_get_first() & xhtab_get_next() functions. 145 ****************************************************************************************** 146 * @ xhtab_xp : extended pointer on hash table. 147 *****************************************************************************************/ 148 void xhtab_read_lock( xptr_t xhtab_xp ); 149 150 /****************************************************************************************** 151 * This function releases the lock protecting exclusive access to the hash table. 152 * It should be called after the xhtab_get_first() & xhtab_get_next() functions. 153 ****************************************************************************************** 154 * @ xhtab_xp : extended pointer on hash table. 155 *****************************************************************************************/ 156 void xhtab_read_unlock( xptr_t xhtab_xp ); 157 158 /****************************************************************************************** 159 * This function returns an extended pointer on the first item registered in hash table, 160 * and register this pointer in the hash table header. 161 * The lock protecting the hash table must have been previously taken by the caller. 162 ****************************************************************************************** 163 * @ xhtab_xp : extended pointer on hash table. 164 * @ return extended pointer on item if success / XPTR_NULL if not found. 165 *****************************************************************************************/ 166 xptr_t xhtab_get_first( xptr_t xhtab_xp ); 167 168 /****************************************************************************************** 169 * This function returns an extended pointer on item following the currently pointed 170 * item in the hash table header. 171 * The lock protecting the hash table must have been previously taken by the caller. 172 ****************************************************************************************** 173 * @ xhtab_xp : extended pointer on hash table. 174 * @ return extended pointer on item if success / XPTR_NULL if not found. 175 *****************************************************************************************/ 176 xptr_t xhtab_get_next( xptr_t xhtab_xp ); 177 178 133 179 134 180 #endif /* _XHTAB_H_ */ -
trunk/kernel/mm/kcm.h
r161 r188 98 98 99 99 /**************************************************************************************** 100 * This function allocates one single object ina Kernel Cache Manager100 * This function allocates one single object from a Kernel Cache Manager 101 101 * The object size must be smaller than one page size. 102 102 **************************************************************************************** -
trunk/kernel/mm/kmem.c
r181 r188 82 82 uint32_t kmem_type_size( uint32_t type ) 83 83 { 84 if ( type == KMEM_PAGE ) return CONFIG_PPM_PAGE_SIZE; 85 else if( type == KMEM_GENERIC ) return 0; 86 else if( type == KMEM_KCM ) return sizeof( kcm_t ); 87 else if( type == KMEM_VSEG ) return sizeof( vseg_t ); 88 else if( type == KMEM_DEVICE ) return sizeof( chdev_t ); 89 else if( type == KMEM_MAPPER ) return sizeof( mapper_t ); 90 else if( type == KMEM_PROCESS ) return sizeof( process_t ); 91 else if( type == KMEM_CPU_CTX ) return sizeof( hal_cpu_context_t ); 92 else if( type == KMEM_FPU_CTX ) return sizeof( hal_fpu_context_t ); 93 else if( type == KMEM_BARRIER ) return sizeof( remote_barrier_t ); 94 95 else if( type == KMEM_FATFS_INODE ) return sizeof( fatfs_inode_t ); 96 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t ); 97 else if( type == KMEM_DEVFS_INODE ) return sizeof( devfs_inode_t ); 98 else if( type == KMEM_MUTEX ) return sizeof( remote_mutex_t ); 99 else if( type == KMEM_VFS_CTX ) return sizeof( vfs_ctx_t ); 100 else if( type == KMEM_VFS_INODE ) return sizeof( vfs_inode_t ); 101 else if( type == KMEM_VFS_DENTRY ) return sizeof( vfs_dentry_t ); 102 else if( type == KMEM_VFS_FILE ) return sizeof( vfs_file_t ); 103 else if( type == KMEM_SEM ) return sizeof( remote_sem_t ); 104 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t ); 105 84 if ( type == KMEM_PAGE ) return CONFIG_PPM_PAGE_SIZE; 85 else if( type == KMEM_GENERIC ) return 0; 86 else if( type == KMEM_KCM ) return sizeof( kcm_t ); 87 else if( type == KMEM_VSEG ) return sizeof( vseg_t ); 88 else if( type == KMEM_DEVICE ) return sizeof( chdev_t ); 89 else if( type == KMEM_MAPPER ) return sizeof( mapper_t ); 90 else if( type == KMEM_PROCESS ) return sizeof( process_t ); 91 else if( type == KMEM_CPU_CTX ) return CONFIG_CPU_CTX_SIZE; 92 else if( type == KMEM_FPU_CTX ) return CONFIG_FPU_CTX_SIZE; 93 else if( type == KMEM_BARRIER ) return sizeof( remote_barrier_t ); 94 95 else if( type == KMEM_DEVFS_CTX ) return sizeof( fatfs_ctx_t ); 96 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t ); 97 else if( type == KMEM_VFS_CTX ) return sizeof( vfs_ctx_t ); 98 else if( type == KMEM_VFS_INODE ) return sizeof( vfs_inode_t ); 99 else if( type == KMEM_VFS_DENTRY ) return sizeof( vfs_dentry_t ); 100 else if( type == KMEM_VFS_FILE ) return sizeof( vfs_file_t ); 101 else if( type == KMEM_SEM ) return sizeof( remote_sem_t ); 102 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t ); 103 else if( type == KMEM_MUTEX ) return sizeof( remote_mutex_t ); 106 104 else if( type == KMEM_512_BYTES ) return 512; 107 105 … … 123 121 else if( type == KMEM_BARRIER ) return "KMEM_BARRIER"; 124 122 125 else if( type == KMEM_FATFS_INODE ) return "KMEM_FATFS_INODE"; 126 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX"; 127 else if( type == KMEM_DEVFS_INODE ) return "KMEM_DEVFS_INODE"; 128 else if( type == KMEM_MUTEX ) return "KMEM_MUTEX"; 129 else if( type == KMEM_VFS_CTX ) return "KMEM_VFS_CTX"; 130 else if( type == KMEM_VFS_INODE ) return "KMEM_VFS_INODE"; 131 else if( type == KMEM_VFS_DENTRY ) return "KMEM_VFS_DENTRY"; 132 else if( type == KMEM_VFS_FILE ) return "KMEM_VFS_FILE"; 133 else if( type == KMEM_SEM ) return "KMEM_SEM"; 134 else if( type == KMEM_SEM ) return "KMEM_CONDVAR"; 135 123 else if( type == KMEM_DEVFS_CTX ) return "KMEM_DEVFS_CTX"; 124 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX"; 125 else if( type == KMEM_VFS_CTX ) return "KMEM_VFS_CTX"; 126 else if( type == KMEM_VFS_INODE ) return "KMEM_VFS_INODE"; 127 else if( type == KMEM_VFS_DENTRY ) return "KMEM_VFS_DENTRY"; 128 else if( type == KMEM_VFS_FILE ) return "KMEM_VFS_FILE"; 129 else if( type == KMEM_SEM ) return "KMEM_SEM"; 130 else if( type == KMEM_CONDVAR ) return "KMEM_CONDVAR"; 131 else if( type == KMEM_MUTEX ) return "KMEM_MUTEX"; 136 132 else if( type == KMEM_512_BYTES ) return "KMEM_512_BYTES"; 137 133 -
trunk/kernel/mm/kmem.h
r159 r188 48 48 KMEM_BARRIER = 9, /*! remote_barrier_t */ 49 49 50 KMEM_ FATFS_INODE= 10, /*! fatfs_inode_t */50 KMEM_DEVFS_CTX = 10, /*! fatfs_inode_t */ 51 51 KMEM_FATFS_CTX = 11, /*! fatfs_ctx_t */ 52 KMEM_DEVFS_INODE = 12, /* devfs_inode_t */ 53 KMEM_MUTEX = 13, /*! remote_mutex_t */ 54 KMEM_VFS_CTX = 14, /*! vfs_context_t */ 55 KMEM_VFS_INODE = 15, /*! vfs_inode_t */ 56 KMEM_VFS_DENTRY = 16, /*! vfs_dentry_t */ 57 KMEM_VFS_FILE = 17, /*! vfs_file_t */ 58 KMEM_SEM = 18, /*! remote_sem_t */ 59 KMEM_CONDVAR = 19, /*! remote_condvar_t */ 60 61 KMEM_512_BYTES = 20, /*! 512 bytes aligned */ 52 KMEM_VFS_CTX = 12, /*! vfs_context_t */ 53 KMEM_VFS_INODE = 13, /*! vfs_inode_t */ 54 KMEM_VFS_DENTRY = 14, /*! vfs_dentry_t */ 55 KMEM_VFS_FILE = 15, /*! vfs_file_t */ 56 KMEM_SEM = 16, /*! remote_sem_t */ 57 KMEM_CONDVAR = 17, /*! remote_condvar_t */ 58 KMEM_MUTEX = 18, /*! remote_mutex_t */ 59 KMEM_512_BYTES = 19, /*! 512 bytes aligned */ 62 60 63 61 KMEM_TYPES_NR = 21, -
trunk/kernel/vfs/devfs.c
r50 r188 26 26 #include <hal_special.h> 27 27 #include <printk.h> 28 #include <chdev.h> 29 #include <cluster.h> 30 #include <vfs.h> 28 31 #include <kmem.h> 29 #include <string.h>30 #include <chdev.h>31 #include <core.h>32 #include <thread.h>33 #include <vfs.h>34 #include <errno.h>35 32 #include <devfs.h> 36 #include <rpc.h> 37 38 39 ////////////////////////////////////////////////////////////////////////////////////////// 40 // Extern variables 41 ////////////////////////////////////////////////////////////////////////////////////////// 42 43 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in vfs.c file 44 45 extern remote_barrier_t global_barrier; // allocated in kernel_init.c 46 47 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 48 49 //////////////////////////////////////////////////////////////////////////////////////// 50 // DEVFS private functions 51 //////////////////////////////////////////////////////////////////////////////////////// 52 53 //////////////////////////////////////////////////////////////////////////////////////// 54 // This function creates in the local cluster the dentry and the associated inode, 55 // for a DEVFS directory (level 0 or level 1 in DEVFS tree). 56 //////////////////////////////////////////////////////////////////////////////////////// 57 // @ name : directory entry name. 58 // @ parent_xp : extended pointer on parent inode. 59 // @ inode_xp : [out] buffer for extended pointer on created inode. 60 //////////////////////////////////////////////////////////////////////////////////////// 61 static void devfs_create_directory( char * name, 62 xptr_t parent_xp, 63 xptr_t * inode_xp ) 64 { 65 error_t error; 66 xptr_t new_dentry_xp; // extended pointer on created dentry 67 xptr_t new_inode_xp; // extended pointer on created inode 68 69 // get parent inode cluster and local pointer 70 cxy_t parent_cxy = GET_CXY( parent_xp ); 71 vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 72 73 // create vfs_dentry in cluster containing the parent inode 74 if( parent_cxy == local_cxy ) 75 { 76 error = vfs_dentry_create( FS_TYPE_DEVFS, 77 name, 78 parent_ptr, 79 &new_dentry_xp ); 80 } 81 else 82 { 83 rpc_vfs_dentry_create_client( parent_cxy, 84 FS_TYPE_DEVFS, 85 name, 86 parent_ptr, 87 &new_dentry_xp, 88 &error ); 89 } 90 91 if ( error ) 92 { 93 printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n", 94 __FUNCTION__ , name , local_cxy ); 95 hal_core_sleep(); 96 } 97 98 // create vfs_inode in local cluster TODO define the 4 arguments below [AG] 99 uint32_t attr = 0; 100 uint32_t rights = 0; 101 uid_t uid = 0; 102 gid_t gid = 0; 103 error = vfs_inode_create( new_dentry_xp, 104 FS_TYPE_DEVFS, 105 INODE_TYPE_DIR, 106 attr, 107 rights, 108 uid, 109 gid, 110 &new_inode_xp ); 111 if( error ) 112 { 113 printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n", 114 __FUNCTION__ , name , local_cxy ); 115 hal_core_sleep(); 116 } 117 118 // return extended pointer on directory inode 119 *inode_xp = new_inode_xp; 120 121 } // end devfs_create_directory() 122 123 //////////////////////////////////////////////////////////////////////////////////////// 124 // This function creates in the local cluster the dentry and the associated inode, 125 // for a chdev (level 2 in DEVFS tree). 126 //////////////////////////////////////////////////////////////////////////////////////// 127 // @ chdev : local pointer on local chdev. 128 // @ name : directory entry name. 129 // @ parent : local pointer on local parent inode. 130 // @ inode_xp : [out] buffer for extended pointer on created inode. 131 //////////////////////////////////////////////////////////////////////////////////////// 132 static void devfs_register_chdev( chdev_t * chdev, 133 char * name, 134 vfs_inode_t * parent, 135 xptr_t * inode_xp ) 33 34 ///////////////////////////////////////////////////////////////////////////////////////// 35 // Extern variables 36 ///////////////////////////////////////////////////////////////////////////////////////// 37 38 extern vfs_ctx_t fs_context[]; // allocated in kernel_init.c 39 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 40 41 /////////////////////////////// 42 devfs_ctx_t * devfs_ctx_alloc() 43 { 44 kmem_req_t req; 45 46 req.type = KMEM_DEVFS_CTX; 47 req.size = sizeof(devfs_ctx_t); 48 req.flags = AF_KERNEL | AF_ZERO; 49 50 return (devfs_ctx_t *)kmem_alloc( &req ); 51 } 52 53 ///////////////////////////////////////////// 54 void devfs_ctx_init( devfs_ctx_t * devfs_ctx, 55 xptr_t devfs_root_inode_xp, 56 xptr_t devfs_external_inode_xp ) 57 { 58 devfs_ctx->root_inode_xp = devfs_root_inode_xp; 59 devfs_ctx->external_inode_xp = devfs_external_inode_xp; 60 61 fs_context[FS_TYPE_DEVFS].extend = devfs_ctx; 62 } 63 64 ///////////////////////////////////////////////// 65 void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx ) 66 { 67 kmem_req_t req; 68 69 req.type = KMEM_DEVFS_CTX; 70 req.ptr = devfs_ctx; 71 kmem_free( &req ); 72 } 73 74 /////////////////////////////////////////////////// 75 void devfs_global_init( xptr_t parent_inode_xp, 76 xptr_t * devfs_root_inode_xp, 77 xptr_t * devfs_external_inode_xp ) 136 78 { 137 79 error_t error; 138 xptr_t new_dentry_xp; 139 xptr_t new_inode_xp; 140 141 devfs_dmsg("\n[INFO] %s : create dentry for %s\n", __FUNCTION__ , name ); 142 143 // create vfs_dentry in local cluster 144 error = vfs_dentry_create( FS_TYPE_DEVFS, 145 name, 146 parent, 147 &new_dentry_xp ); 148 if ( error ) 149 { 150 printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n", 151 __FUNCTION__ , name , local_cxy ); 152 hal_core_sleep(); 153 } 154 155 devfs_dmsg("\n[INFO] %s : create inode for %s\n", __FUNCTION__ , name ); 156 157 // create vfs_inode in local cluster 158 uint32_t attr = 0; 159 uint32_t rights = 0; 160 uid_t uid = 0; 161 gid_t gid = 0; 162 error = vfs_inode_create( new_dentry_xp, 163 FS_TYPE_DEVFS, 164 INODE_TYPE_DEV, 165 attr, 166 rights, 167 uid, 168 gid, 169 &new_inode_xp ); 170 if( error ) 171 { 172 printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n", 173 __FUNCTION__ , name , local_cxy ); 174 hal_core_sleep(); 175 } 176 177 // return extended pointer on chdev inode 178 *inode_xp = new_inode_xp; 179 180 } // end devfs_register_chdev() 181 182 183 184 /////////////////////////////////////////////////////////////////////////////////////// 185 // Generic API : the following functions are called by the VFS, 186 // and must be defined by all supported file systems. 187 /////////////////////////////////////////////////////////////////////////////////////// 188 189 //////////////////////////////////////////// 190 191 //////////////////////////////////////////// 192 error_t devfs_mount( xptr_t parent_inode_xp, 193 char * devfs_root_name ) 194 { 195 assert( (CURRENT_CORE->lid == 0) , __FUNCTION__ , "only CP0 should do it" ); 196 197 vfs_inode_t * parent_inode_ptr; 198 cxy_t parent_inode_cxy; 199 vfs_ctx_t * vfs_ctx; 200 80 81 // creates DEVFS "dev" inode in cluster IO 82 error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy, 83 INODE_TYPE_DIR, 84 FS_TYPE_DEVFS, 85 parent_inode_xp, 86 "dev", 87 NULL, 88 devfs_root_inode_xp ); 89 90 nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <dev>\n" ); 91 92 // create DEVFS "external" inode in cluster IO 93 error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy, 94 INODE_TYPE_DIR, 95 FS_TYPE_DEVFS, 96 *devfs_root_inode_xp, 97 "dev", 98 NULL, 99 devfs_external_inode_xp ); 100 101 nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" ); 102 } 103 104 ////////////////////////////////////////////////// 105 void devfs_local_init( xptr_t devfs_root_inode_xp, 106 xptr_t devfs_external_inode_xp ) 107 { 201 108 char node_name[16]; 109 xptr_t chdev_xp; 110 cxy_t chdev_cxy; 111 xptr_t inode_xp; 112 xptr_t internal_inode_xp; 202 113 uint32_t channel; 203 114 204 xptr_t root_inode_xp; 205 xptr_t external_inode_xp; 206 xptr_t internal_inode_xp; 207 xptr_t chdev_inode_xp; 208 209 chdev_t * chdev_ptr; 210 211 // get number of kernel instances and extended pointer on global barrier 212 cluster_t * cluster = LOCAL_CLUSTER; 213 uint32_t nb_clusters = cluster->x_size * cluster->y_size; 214 xptr_t barrier_xp = XPTR( cluster->io_cxy , &global_barrier ); 215 216 // get VFS root inode cluster and local pointer 217 parent_inode_cxy = GET_CXY( parent_inode_xp ); 218 parent_inode_ptr = (vfs_inode_t *)GET_PTR( parent_inode_xp ); 219 220 // get local pointer on VFS context for DEVFS 221 vfs_ctx = &fs_context[FS_TYPE_DEVFS]; 222 223 ///// step 1 : all clusters initialize local DEVFS context ///// 224 225 devfs_ctx_init( vfs_ctx , parent_inode_xp ); 226 227 ///// step 2 : cluster_0 creates DEVFS root ///// 228 229 if( local_cxy == 0 ) 230 { 231 devfs_create_directory( devfs_root_name, 232 parent_inode_xp, 233 &root_inode_xp ); 234 } 235 236 // synchronize all clusters 237 remote_barrier( barrier_xp , nb_clusters ); 238 239 ///// step 3 : all clusters create "internal" directory and chdevs ///// 240 241 // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir 242 115 // create "internal" directory linked to "dev" 243 116 snprintf( node_name , 16 , "internal_%x" , local_cxy ); 244 245 devfs_create_directory( node_name, 246 root_inode_xp, 247 &internal_inode_xp ); 117 vfs_add_child_in_parent( local_cxy, 118 INODE_TYPE_DIR, 119 FS_TYPE_DEVFS, 120 devfs_root_inode_xp, 121 node_name, 122 NULL, 123 &internal_inode_xp ); 248 124 249 125 // create ICU chdev inode 250 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.icu[local_cxy] ); 251 devfs_register_chdev( chdev_ptr, 252 "icu", 253 (vfs_inode_t *)GET_PTR( internal_inode_xp ), 254 &chdev_inode_xp ); 126 chdev_xp = chdev_dir.icu[local_cxy]; 127 if( chdev_xp != XPTR_NULL) 128 { 129 vfs_add_child_in_parent( local_cxy, 130 INODE_TYPE_DEV, 131 FS_TYPE_DEVFS, 132 internal_inode_xp, 133 "icu", 134 GET_PTR( chdev_xp ), 135 &inode_xp ); 136 } 255 137 256 138 // create MMC chdev inode 257 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.mmc[local_cxy] ); 258 devfs_register_chdev( chdev_ptr, 259 "mmc", 260 (vfs_inode_t *)GET_PTR( internal_inode_xp ), 261 &chdev_inode_xp ); 139 chdev_xp = chdev_dir.mmc[local_cxy]; 140 if( chdev_xp != XPTR_NULL) 141 { 142 vfs_add_child_in_parent( local_cxy, 143 INODE_TYPE_DEV, 144 FS_TYPE_DEVFS, 145 internal_inode_xp, 146 "mmc", 147 GET_PTR( chdev_xp ), 148 &inode_xp ); 149 } 262 150 263 151 // create DMA chdev inodes (one DMA channel per core) 264 for( channel = 0 ; channel < cluster->cores_nr ; channel++ ) 265 { 266 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.dma[channel] ); 267 snprintf( node_name , 16 , "dma_%d" , channel ); 268 devfs_register_chdev( chdev_ptr, 269 node_name, 270 (vfs_inode_t *)GET_PTR( internal_inode_xp ), 271 &chdev_inode_xp ); 272 } 273 274 ///// step 4 : cluster_io creates "external" directory and chdevs ///// 275 276 // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir 277 278 if( local_cxy == cluster->io_cxy ) 279 { 280 devfs_create_directory( "external", 281 root_inode_xp, 282 &external_inode_xp ); 283 284 // create IOB chdev inode 285 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.iob ); 286 devfs_register_chdev( chdev_ptr, 287 "iob", 288 (vfs_inode_t *)GET_PTR( external_inode_xp ), 289 &chdev_inode_xp ); 152 for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ ) 153 { 154 chdev_xp = chdev_dir.dma[channel]; 155 if( chdev_xp != XPTR_NULL) 156 { 157 snprintf( node_name , 16 , "dma_%d" , channel ); 158 vfs_add_child_in_parent( local_cxy, 159 INODE_TYPE_DEV, 160 FS_TYPE_DEVFS, 161 internal_inode_xp, 162 node_name, 163 GET_PTR( chdev_xp ), 164 &inode_xp ); 165 } 166 } 167 168 // create an IOB inode in cluster containing IOB chdev 169 chdev_xp = chdev_dir.iob; 170 if( chdev_xp != XPTR_NULL ) 171 { 172 chdev_cxy = GET_CXY( chdev_xp ); 173 if( chdev_cxy == local_cxy ) 174 { 175 vfs_add_child_in_parent( local_cxy, 176 INODE_TYPE_DEV, 177 FS_TYPE_DEVFS, 178 devfs_external_inode_xp, 179 "iob", 180 GET_PTR( chdev_xp ), 181 &inode_xp ); 182 } 183 } 290 184 291 // create PIC chdev inode 292 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.pic ); 293 devfs_register_chdev( chdev_ptr, 294 "pic", 295 (vfs_inode_t *)GET_PTR( external_inode_xp ), 296 &chdev_inode_xp ); 297 298 // create TXT chdev inodes 299 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ ) 300 { 301 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.txt[channel] ); 302 snprintf( node_name , 16 , "txt_%d" , channel ); 303 devfs_register_chdev( chdev_ptr, 304 node_name, 305 (vfs_inode_t *)GET_PTR( external_inode_xp ), 306 &chdev_inode_xp ); 307 } 308 309 // create IOC chdev inodes 310 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 311 { 312 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); 313 snprintf( node_name , 16 , "ioc_%d" , channel ); 314 devfs_register_chdev( chdev_ptr, 315 node_name, 316 (vfs_inode_t *)GET_PTR( external_inode_xp ), 317 &chdev_inode_xp ); 318 } 319 320 // create FBF chdev inodes 321 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 322 { 323 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); 324 snprintf( node_name , 16 , "fbf_%d" , channel ); 325 devfs_register_chdev( chdev_ptr, 326 node_name, 327 (vfs_inode_t *)GET_PTR( external_inode_xp ), 328 &chdev_inode_xp ); 329 } 330 331 // create NIC_RX chdevs 332 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 333 { 334 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_rx[channel] ); 335 snprintf( node_name , 16 , "nic_rx_%d" , channel ); 336 devfs_register_chdev( chdev_ptr, 337 node_name, 338 (vfs_inode_t *)GET_PTR( external_inode_xp ), 339 &chdev_inode_xp ); 340 } 341 342 // create NIC_TX chdev inodes 343 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 344 { 345 chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_tx[channel] ); 346 snprintf( node_name , 16 , "nic_tx_%d" , channel ); 347 devfs_register_chdev( chdev_ptr, 348 node_name, 349 (vfs_inode_t *)GET_PTR( external_inode_xp ), 350 &chdev_inode_xp ); 351 } 352 } 353 354 // synchronize all clusters 355 remote_barrier( barrier_xp , nb_clusters ); 356 357 return 0; 358 359 } // end devfs_init() 360 361 362 //////////////////////////////////////////// 363 error_t devfs_ctx_init( vfs_ctx_t * vfs_ctx, 364 xptr_t root_inode_xp ) 365 { 366 vfs_ctx->type = FS_TYPE_DEVFS; 367 vfs_ctx->attr = 0; // not READ_ONLY / not SYNC 368 vfs_ctx->count = 0; // unused for DEVFS 369 vfs_ctx->blksize = 0; // unused for DEVFS 370 vfs_ctx->root_xp = root_inode_xp; 371 vfs_ctx->extend = NULL; // unused for DEVFS 372 373 spinlock_init( &vfs_ctx->lock ); 374 375 bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES ); 376 377 return 0; 378 } 379 380 381 //////////////////////////////////////////////////// 382 error_t devfs_inode_create( vfs_inode_t * vfs_inode, 383 chdev_t * chdev ) 384 { 385 kmem_req_t req; 386 devfs_inode_t * devfs_inode; 387 388 // allocate memory for FATFS inode extension 389 req.type = KMEM_DEVFS_INODE; 390 req.size = sizeof(devfs_inode_t); 391 req.flags = AF_KERNEL | AF_ZERO; 392 devfs_inode = (devfs_inode_t *)kmem_alloc( &req ); 393 394 if( devfs_inode == NULL ) return ENOMEM; 395 396 // link DEVFS inode to VFS inode 397 vfs_inode->extend = devfs_inode; 398 399 // initialise DEVFS inode 400 devfs_inode->chdev = chdev; 401 402 return 0; 403 } 404 405 /////////////////////////////////////////////////// 406 void devfs_inode_destroy( vfs_inode_t * vfs_inode ) 407 { 408 kmem_req_t req; 409 devfs_inode_t * devfs_inode; 410 411 // get pointer on DEVFS inode 412 devfs_inode = (devfs_inode_t *)vfs_inode->extend; 413 414 req.type = KMEM_DEVFS_INODE; 415 req.ptr = devfs_inode; 416 kmem_free( &req ); 417 418 vfs_inode->extend = NULL; 419 } 420 421 422 /* deprecated [AG] 423 424 error_t devfs_open_file( vfs_file_t * file, 425 void * extend ); 426 { 427 error_t err; 428 register struct devfs_context_s *ctx; 429 register struct devfs_file_s *info; 430 chdev_t * chdev; 431 vfs_inode_t * inode; 432 dev_request_t rq; 433 kmem_req_t req; 434 435 inode = file->inode; 436 437 info = file->fr_pv; 438 ctx = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs; 439 440 if(!(inode->i_attr & VFS_DIR)) 441 { 442 dev = (struct device_s*)inode->i_pv; 443 444 if(dev->type == DEV_INTERNAL) 445 return EPERM; 446 447 if(dev->type == DEV_BLK) 448 VFS_SET(inode->i_attr,VFS_DEV_BLK); 449 else 450 VFS_SET(inode->i_attr,VFS_DEV_CHR); 451 452 if(dev->op.dev.open != NULL) 453 { 454 rq.fremote = file; 455 if((err=dev->op.dev.open(dev, &rq))) 456 return err; 457 } 458 459 priv->dev = (void*)dev; 460 461 return 0; 462 } 463 464 if(info == NULL) 465 { 466 req.type = KMEM_DEVFS_FILE; 467 req.size = sizeof(*info); 468 req.flags = AF_KERNEL; 469 info = kmem_alloc(&req); 470 } 471 472 if(info == NULL) return ENOMEM; 473 474 metafs_iter_init(&devfs_db.root, &info->iter); 475 info->ctx = ctx; 476 file->fr_pv = info; 477 478 metafs_print(&devfs_db.root); 479 return 0; 480 } 481 482 #define TMP_BUFF_SZ 512 483 484 //FIXME: 485 //add a "while" loop for the case where the 486 //buffer TMP_BUFF_SZ is smaller than 487 //buffer->size 488 ////////////////////////////// 489 devfs_read( vfs_file_t * file, 490 char * buffer ) 491 { 492 chdev_t * chdev; 493 dev_request_t rq; 494 uint32_t count; 495 uint8_t buff[TMP_BUFF_SZ]; 496 497 // get pointer on chdev 498 chdev = (chdev_t *)file->extend; 499 500 if( chdev->func == DEV_FUNC_TXT ) 501 { 502 } 503 if( chdev->func == DEV_FUNC_IOC ) 504 { 505 } 506 else 507 { 508 printk("\n[PANIC] in %s : illegal device functionnal type 509 510 rq.dst = &buff[0]; 511 rq.count = TMP_BUFF_SZ; 512 rq.flags = 0; 513 rq.file = file; 514 515 if((count = dev->op.dev.read(dev, &rq)) < 0) 516 return count; 517 518 buffer->scpy_to_buff(buffer, &buff[0], count); 519 return count; 520 } 521 522 //FIXME: To improve this an avoid the extra copy, 523 //we could set along with the buffer(src and dest) 524 //the functions to manipulate them, such as in 525 //do_exec.c 526 /////////////////////////////// 527 devfs_write( vfs_file_t * file, 528 char * buffer ) 529 { 530 register struct device_s *dev; 531 uint8_t buff[TMP_BUFF_SZ]; 532 dev_request_t rq; 533 534 dev = (struct device_s*)file->f_private.dev; 535 536 //FIXME avoid the extra copy ? 537 buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ); 538 rq.src = (void*)&buff[0]; 539 rq.count = buffer->size; 540 rq.flags = 0; 541 rq.file = file; 542 543 return dev->op.dev.write(dev, &rq); 544 } 545 546 VFS_LSEEK_FILE(devfs_lseek) 547 { 548 register struct device_s *dev; 549 dev_request_t rq; 550 551 dev = (struct device_s*)file->fr_inode->i_pv; 552 553 if(dev->op.dev.lseek == NULL) 554 return VFS_ENOTUSED; 555 556 rq.fremote = file; 557 return dev->op.dev.lseek(dev, &rq); 558 } 559 560 VFS_CLOSE_FILE(devfs_close) 561 { 562 register struct device_s *dev; 563 dev_request_t rq; 564 565 if(file->fr_inode->i_attr & VFS_DIR) 566 return 0; 567 568 dev = (struct device_s*)file->fr_inode->i_pv; 569 570 if(dev->op.dev.close == NULL) 571 return 0; 572 573 rq.fremote = file; 574 return dev->op.dev.close(dev, &rq); 575 } 576 577 VFS_RELEASE_FILE(devfs_release) 578 { 579 kmem_req_t req; 580 581 if(file->fr_pv == NULL) 582 return 0; 583 584 req.type = KMEM_DEVFS_FILE; 585 req.ptr = file->fr_pv; 586 kmem_free(&req); 587 588 file->fr_pv = NULL; 589 return 0; 590 } 591 592 VFS_READ_DIR(devfs_readdir) 593 { 594 register struct devfs_file_s *info; 595 register struct metafs_s *current; 596 register struct device_s *current_dev; 597 598 info = file->fr_pv; 599 600 if(file->fr_pv == NULL) 601 return ENOTDIR; 602 603 if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL) 604 return EEODIR; 605 606 current_dev = metafs_container(current, struct device_s, node); 607 dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR; 608 609 strcpy((char*)dirent->u_name, metafs_get_name(current)); 610 611 dirent->u_ino = (uint_t) current_dev->base_paddr; 612 613 return 0; 614 } 615 616 VFS_MMAP_FILE(devfs_mmap) 617 { 618 register struct device_s *dev; 619 dev_request_t rq; 620 621 dev = (struct device_s*)file->f_private.dev; 622 623 if(dev->op.dev.mmap == NULL) 624 return ENODEV; 625 626 rq.flags = 0; 627 rq.file = file; 628 rq.region = region; 629 630 return dev->op.dev.mmap(dev, &rq); 631 } 632 633 VFS_MMAP_FILE(devfs_munmap) 634 { 635 register struct device_s *dev; 636 dev_request_t rq; 637 638 dev = (struct device_s*)file->f_private.dev; 639 640 if(dev->op.dev.munmap == NULL) 641 return ENODEV; 642 643 rq.flags = 0; 644 rq.file = file; 645 rq.region = region; 646 647 return dev->op.dev.munmap(dev, &rq); 648 } 649 650 651 */ 652 653 185 // create a PIC inode in cluster containing PIC chdev 186 chdev_xp = chdev_dir.pic; 187 if( chdev_xp != XPTR_NULL ) 188 { 189 chdev_cxy = GET_CXY( chdev_xp ); 190 if( chdev_cxy == local_cxy ) 191 { 192 vfs_add_child_in_parent( local_cxy, 193 INODE_TYPE_DEV, 194 FS_TYPE_DEVFS, 195 devfs_external_inode_xp, 196 "pic", 197 GET_PTR( chdev_xp ), 198 &inode_xp ); 199 } 200 } 201 202 // create a TXT inode in each cluster containing a TXT chdev 203 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ ) 204 { 205 chdev_xp = chdev_dir.txt[channel]; 206 if( chdev_xp != XPTR_NULL ) 207 { 208 chdev_cxy = GET_CXY( chdev_xp ); 209 if( chdev_cxy == local_cxy ) 210 { 211 snprintf( node_name , 16 , "txt_%d" , channel ); 212 vfs_add_child_in_parent( local_cxy, 213 INODE_TYPE_DEV, 214 FS_TYPE_DEVFS, 215 devfs_external_inode_xp, 216 node_name, 217 GET_PTR( chdev_xp ), 218 &inode_xp ); 219 } 220 } 221 } 222 223 // create an IOC inode in each cluster containing an IOC chdev 224 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 225 { 226 chdev_xp = chdev_dir.ioc[channel]; 227 if( chdev_xp != XPTR_NULL ) 228 { 229 chdev_cxy = GET_CXY( chdev_xp ); 230 if( chdev_cxy == local_cxy ) 231 { 232 snprintf( node_name , 16 , "ioc_%d" , channel ); 233 vfs_add_child_in_parent( local_cxy, 234 INODE_TYPE_DEV, 235 FS_TYPE_DEVFS, 236 devfs_external_inode_xp, 237 node_name, 238 GET_PTR( chdev_xp ), 239 &inode_xp ); 240 } 241 } 242 } 243 244 // create a FBF inode in each cluster containing a FBF chdev 245 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 246 { 247 chdev_xp = chdev_dir.fbf[channel]; 248 if( chdev_xp != XPTR_NULL ) 249 { 250 chdev_cxy = GET_CXY( chdev_xp ); 251 if( chdev_cxy == local_cxy ) 252 { 253 snprintf( node_name , 16 , "fbf_%d" , channel ); 254 vfs_add_child_in_parent( local_cxy, 255 INODE_TYPE_DEV, 256 FS_TYPE_DEVFS, 257 devfs_external_inode_xp, 258 node_name, 259 GET_PTR( chdev_xp ), 260 &inode_xp ); 261 } 262 } 263 } 264 265 // create a NIC_RX inode in each cluster containing a NIC_RX chdev 266 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 267 { 268 chdev_xp = chdev_dir.nic_rx[channel]; 269 if( chdev_xp != XPTR_NULL ) 270 { 271 chdev_cxy = GET_CXY( chdev_xp ); 272 if( chdev_cxy == local_cxy ) 273 { 274 snprintf( node_name , 16 , "nic_rx_%d" , channel ); 275 vfs_add_child_in_parent( local_cxy, 276 INODE_TYPE_DEV, 277 FS_TYPE_DEVFS, 278 devfs_external_inode_xp, 279 node_name, 280 GET_PTR( chdev_xp ), 281 &inode_xp ); 282 } 283 } 284 } 285 286 // create a NIC_TX inode in each cluster containing a NIC_TX chdev 287 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 288 { 289 chdev_xp = chdev_dir.nic_tx[channel]; 290 if( chdev_xp != XPTR_NULL ) 291 { 292 chdev_cxy = GET_CXY( chdev_xp ); 293 if( chdev_cxy == local_cxy ) 294 { 295 snprintf( node_name , 16 , "nic_tx_%d" , channel ); 296 vfs_add_child_in_parent( local_cxy, 297 INODE_TYPE_DEV, 298 FS_TYPE_DEVFS, 299 devfs_external_inode_xp, 300 node_name, 301 GET_PTR( chdev_xp ), 302 &inode_xp ); 303 } 304 } 305 } 306 } // end devfs_local_init() 307 -
trunk/kernel/vfs/devfs.h
r23 r188 26 26 #define _DEVFS_H_ 27 27 28 ////////////////////////////////////////////////////////////////////////////////////////// /29 // The DEVFS File System contains inodes a ssociated to all chdev descriptors availables30 // in the target architecture. It is a three levels tree structure:31 // - The "dev" directory inode is stored in cluster_ 0. It is the root of the devfs32 // file system. The parent inode is the "/" globalroot.28 ////////////////////////////////////////////////////////////////////////////////////////// 29 // The DEVFS File System contains inodes and dentries associated to all chdev descriptors 30 // availables in the architecture. It is structured as a three levels tree structure : 31 // - The "dev" directory inode is stored in cluster_IO. It is the root of the DEVFS 32 // file system. The parent inode is the "/" VFS root. 33 33 // - There is one "internal_cxy" directory inode per cluster, that is the parent of 34 // the local children inodes associated to the local chdev descriptors.35 // The parent inode and dentry are stored in cluster_0.34 // the local children inodes associated to the local, internal chdev descriptors. 35 // The parent dentry is stored in cluster_IO. 36 36 // - The I/O cluster contains one "external" directory inode, that is the parent of 37 // the remote children inodes associated to the remote external descriptors.38 // The parent inode and dentry are stored in cluster_0.37 // the remote children inodes associated to the remote external chdev descriptors. 38 // The parent dentry is stored in cluster_IO. 39 39 // 40 // The DEVFS File system does not require a context extension, but requires an inode 41 // extension to store the pointer on the associated chdev descriptor. 42 /////////////////////////////////////////////////////////////////////////////////////////// 40 // The DEVFS file system uses the DEVFS context extension to register an extended pointer 41 // on the DEVFS "dev" inode, and and another extended pointer on the "external" inode. 42 // 43 // The DEVFS file system uses the VFS inode extension to store the pointer 44 // on the associated chdev descriptor. 45 ////////////////////////////////////////////////////////////////////////////////////////// 43 46 44 /************** Forward declarations ************************************************/ 47 /***************************************************************************************** 48 * This structure defines the DEVFS context extension. 49 ****************************************************************************************/ 45 50 46 struct chdev_s; 47 48 /****************************************************************************************** 49 * This structure defines the DEVFS inode descriptor extension. 50 *****************************************************************************************/ 51 52 typedef struct devfs_inode_ext_s 51 typedef struct devfs_ctx_s 53 52 { 54 struct chdev_s * chdev; /* extended pointer on associated chdev */ 53 xptr_t root_inode_xp; /*! extended pointer on DEVFS root inode */ 54 xptr_t external_inode_xp; /*! extended pointer on DEVFS external inode */ 55 55 } 56 devfs_ inode_t;56 devfs_ctx_t; 57 57 58 58 59 60 61 62 ////////////////////////////////////////////////////////////////////////////////////////// 63 // These functions are called by the VFS. 64 ////////////////////////////////////////////////////////////////////////////////////////// 65 66 /****************************************************************************************** 67 * This function does not exist for the DEVFS file system, as this File System 68 * cannot be mounted as the root FS. 69 *****************************************************************************************/ 70 xptr_t devfs_init(); 71 72 73 /****************************************************************************************** 74 * This function mount the DEVFS file system on the root FS. 75 * It is executed cooperatively during kernel init by all CP0s in all clusters, 76 * to create the DEVFS 3-levels tree structure. 77 * This is a four phases procedure, and it uses the global barrier to synchronize 78 * the cooperating kernel instances when required. 79 * - phase 1 : In all clusters, it creates the local extension of the DEVFS context, 80 * and initialises it. 81 * - phase 2 : In cluster_0 only, it creates the dentry and the associated inode for 82 * the DEVFS root directory. 83 * - phase 3 : In all cluster(x,y), it creates the dentry and the associated inode for 84 * the "internal_cxy" directory. It also creates the dentry and associated inode 85 * for all local internal chdevs. 86 * - phase 4 : In cluster_io only, it creates the dentry and the associated inode 87 * for the "external" directory. It also creates the dentry and associated inode 88 * for all external chdevs. 89 ****************************************************************************************** 90 * @ parent_inode_xp : extended pointer on the parent inode in root FS. 91 * @ devfs_root_name : DEVFS root directory name. 92 *****************************************************************************************/ 93 error_t devfs_mount( xptr_t parent_inode_xp, 94 char * devfs_root_name ); 59 /***************************************************************************************** 60 * This fuction allocates memory from local cluster for a DEVFS context descriptor. 61 ***************************************************************************************** 62 * @ return a pointer on the created context / return NULL if failure. 63 ****************************************************************************************/ 64 devfs_ctx_t * devfs_ctx_alloc(); 95 65 96 66 /***************************************************************************************** 97 * This function initiali zes all fields of the VFS context.98 * No extra memory is allocated for a DEVFS context.67 * This function initialises the DEVFS context from arguments values, and link it 68 * to the relevant VFS context in the local cluster. 99 69 ***************************************************************************************** 100 * @ vfs_ctx : local pointer on VFS context for FATFS. 101 * @ root_inode_xp : extended pointer on the VFS root inode. 70 * @ devfs_ctx : local pointer on DEVFS context. 71 * @ devfs_root_inode_xp : [out] extended pointer on created <dev> inode. 72 * @ devfs_external_inode_xp : [out] extended pointer on created <external> inode. 102 73 ****************************************************************************************/ 103 error_t devfs_ctx_init( struct vfs_ctx_s * vfs_ctx, 104 xptr_t root_inode_xp ); 74 void devfs_ctx_init( devfs_ctx_t * devfs_ctx, 75 xptr_t devfs_root_inode_xp, 76 xptr_t devfs_external_inode_xp ); 105 77 106 78 /***************************************************************************************** 107 * This function does not exist for a DEVFS context, as there is no DEVFS context. 79 * This function releases memory dynamically allocated for the DEVFS context. 80 ***************************************************************************************** 81 * @ devfs_ctx : local pointer on DEVFS context. 108 82 ****************************************************************************************/ 109 error_t devfs_ctx_destroy();83 void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx ); 110 84 111 85 /***************************************************************************************** 112 * This function allocates memory for a DEVFS inode, initialise it, 113 * and link it to the VFS inode. 86 * This function start to create the DEVFS subtree. 87 * This function should be called once in the cluster containing the VFS parent inode. 88 * More precisely, it creates in cluster IO the "dev" and "external" DEVFS directories. 89 * For each one, it creates the inode and link the associated dentry to parent inode. 90 * The DEVFS root inode is linked to the VFS parent inode identified by <parent_inode_xp>. 114 91 ***************************************************************************************** 115 * @ inode : local pointer on the VFS inode. 116 * @ chdev : local pointer on the chdev to be inserted in DEVFS. 92 * @ parent_inode_xp : extended pointer on the parent VFS inode. 93 * @ devfs_root_inode_xp : [out] extended pointer on created <dev> inode. 94 * @ devfs_external_inode_xp : [out] extended pointer on created <external> inode. 117 95 ****************************************************************************************/ 118 error_t devfs_inode_create( struct vfs_inode_s * inode, 119 struct chdev_s * chdev ); 96 void devfs_global_init( xptr_t parent_inode_xp, 97 xptr_t * devfs_root_inode_xp, 98 xptr_t * devfs_external_inode_xp ); 120 99 121 100 /***************************************************************************************** 122 * This function releases memory allocated for a DEVFS inode. 101 * This function completes the initialisation of the DEVFS subtree. 102 * It should be called once in each cluster. 103 * 1. In each cluster (i), it creates the "internal" directory, 104 * linked to the DEVFS "dev" parent directory. 105 * 2. In each cluster (i), it creates - for each external chdev in cluster (i) - 106 * a pseudo-file, linked to the DEVFS "external" parent directory. 107 * 3. In each cluster (i), it creates - for each internal chdev in cluster (i) - 108 * a pseudo-file, linked to the DEVFS "internal" parent directory. 123 109 ***************************************************************************************** 124 * @ inode : local pointer on vfs_inode. 110 * @ devfs_root_inode_xp : extended pointer on DEVFS root inode. 111 * @ devfs_external_inode_xp : extended pointer on DEVFS external inode. 125 112 ****************************************************************************************/ 126 void devfs_inode_destroy( struct vfs_inode_s * inode ); 127 128 /***************************************************************************************** 129 * This function does not exist for the DEVFS File System. 130 ****************************************************************************************/ 131 error_t devfs_write_page( struct page_s * page ); 132 133 /***************************************************************************************** 134 * This function does not exist for the DEVFS File System. 135 ****************************************************************************************/ 136 error_t devfs_read_page( struct page_s * page ); 137 138 139 113 void devfs_local_init( xptr_t devfs_root_inode_xp, 114 xptr_t devfs_external_inode_xp ); 115 140 116 #endif /* _DEVFS_H_ */ -
trunk/kernel/vfs/fatfs.c
r101 r188 46 46 47 47 ////////////////////////////////////////////////////////////////////////////////////////// 48 // FATFS specific functions : these functions cannot be called by the VFS 49 ////////////////////////////////////////////////////////////////////////////////////////// 50 51 ////////////////////////////////////////////////////////// 52 inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx, 53 uint32_t cluster ) 48 // FATFS private functions 49 ////////////////////////////////////////////////////////////////////////////////////////// 50 51 ////////////////////////////////////////////////////////////////////////////////////////// 52 // This function returns the LBA of the first sector of a FAT cluster. 53 // This function can be called by any thread running in any cluster. 54 ////////////////////////////////////////////////////////////////////////////////////////// 55 // @ ctx : pointer on FATFS context. 56 // @ cluster : cluster index in FATFS. 57 // @ return the lba value. 58 ////////////////////////////////////////////////////////////////////////////////////////// 59 static inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx, 60 uint32_t cluster ) 54 61 { 55 62 return (ctx->cluster_begin_lba + ((cluster - 2) << 3)); … … 200 207 201 208 /////////////////////////////////////////////////////////////////////////////////////// 202 // The following functions are called by the VFS. 209 // Generic API : the following functions are called by the kernel 210 // and must be defined by all supported file systems. 203 211 /////////////////////////////////////////////////////////////////////////////////////// 204 212 205 206 /////////////////// 207 xptr_t fatfs_init() 213 /////////////////////////////// 214 fatfs_ctx_t * fatfs_ctx_alloc() 208 215 { 209 216 kmem_req_t req; 210 fatfs_ctx_t * fatfs_ctx; // local pointer on FATFS context211 vfs_ctx_t * vfs_ctx; // local pointer on VFS context212 xptr_t root_inode_xp; // extended pointer on root inode213 error_t error;214 215 // get local pointer on VFS context for FATFS216 vfs_ctx = &fs_context[FS_TYPE_FATFS];217 218 // get number of kernel instances and extended pointer on global barrier219 cluster_t * cluster = LOCAL_CLUSTER;220 uint32_t nb_clusters = cluster->x_size * cluster->y_size;221 xptr_t barrier_xp = XPTR( cluster->io_cxy , &global_barrier );222 223 ///// step 1 : all clusters allocate memory for FATFS context224 225 // allocate memory for FATFS context extension226 217 req.type = KMEM_FATFS_CTX; 227 218 req.size = sizeof(fatfs_ctx_t); 228 219 req.flags = AF_KERNEL | AF_ZERO; 229 fatfs_ctx = (fatfs_ctx_t *)kmem_alloc( &req ); 230 231 if( fatfs_ctx == NULL ) 232 { 233 printk("\n[PANIC] in %s : no memory for FATFS context\n", __FUNCTION__ ); 234 hal_core_sleep(); 235 } 236 237 ///// step 2 : only cluster_0 access device and creates root inode 238 239 if( local_cxy == 0 ) 240 { 241 // create VFS root inode 242 error = vfs_inode_create( XPTR_NULL, // no parent dentry 243 FS_TYPE_FATFS, 244 INODE_TYPE_DIR, 245 0, // attr 246 0, // rights 247 0, // uid 248 0, // gid 249 &root_inode_xp ); 250 251 assert( (error == 0 ) , __FUNCTION__ , "cannot create VFS root inode" ); 252 253 // initialize VFS context / access device to initialize FATFS context 254 error = fatfs_ctx_init( vfs_ctx, 255 fatfs_ctx, 256 root_inode_xp ); 257 258 // create FATFS root inode 259 error = fatfs_inode_create( GET_PTR( root_inode_xp ) , 260 fatfs_ctx->root_dir_cluster ); 261 262 if( error ) 263 { 264 printk("\n[PANIC] in %s : cannot create FATFS root inode\n", __FUNCTION__ ); 265 hal_core_sleep(); 266 } 267 268 } 269 270 //////////////// synchronize all clusters 271 remote_barrier( barrier_xp , nb_clusters ); 272 273 ///// step 3 : all others clusters initialize both context and extension 274 275 if( local_cxy != 0 ) 276 { 277 // copy VFS context from remote cluster_0 to local cluster 278 hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 279 XPTR( 0 , vfs_ctx ), 280 sizeof(vfs_ctx_t) ); 281 282 // copy FATFS context from remote cluster_0 to local cluster 283 hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ), 284 XPTR( 0 , vfs_ctx->extend ) , 285 sizeof(fatfs_ctx_t) ); 286 287 // update extend field in local copy of VFS context 288 vfs_ctx->extend = fatfs_ctx; 289 } 290 291 return root_inode_xp; 292 293 } // end fatfs_init() 220 221 return (fatfs_ctx_t *)kmem_alloc( &req ); 222 } 294 223 295 224 ////////////////////////////////////////////// 296 error_t fatfs_ctx_init( vfs_ctx_t * vfs_ctx, 297 fatfs_ctx_t * fatfs_ctx, 298 xptr_t root_inode_xp ) 299 { 300 error_t error; 301 uint8_t * buffer; 302 kmem_req_t req; 225 void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx ) 226 { 227 error_t error; 228 kmem_req_t req; 229 uint8_t * buffer; 230 231 fatfs_dmsg("\n[INFO] %s : enters at cycle %d\n", 232 __FUNCTION__ , hal_get_cycles() ); 233 234 // allocate memory for FATFS context 235 req.type = KMEM_FATFS_CTX; 236 req.size = sizeof(fatfs_ctx_t); 237 req.flags = AF_KERNEL | AF_ZERO; 238 239 fatfs_ctx = (fatfs_ctx_t *)kmem_alloc( &req ); 240 241 nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ , 242 "cannot allocate memory for FATFS context\n" ); 303 243 304 244 // allocate a 512 bytes buffer to store the boot record … … 306 246 req.flags = AF_KERNEL | AF_ZERO; 307 247 buffer = (uint8_t *)kmem_alloc( &req ); 248 249 nolock_assert( (buffer != NULL) , __FUNCTION__ , 250 "cannot allocate memory for 512 bytes buffer\n" ); 308 251 309 fatfs_dmsg("\n[INFO] %s : enters with buffer = %x\n",310 __FUNCTION__ , (intptr_t)buffer );311 312 252 // load the boot record from device 313 253 // using a synchronous access to IOC device 314 254 error = dev_ioc_sync_read( buffer , 0 , 1 ); 315 255 316 assert( (error == 0) , __FUNCTION__ , "cannot access boot record" ); 256 nolock_assert( (error == 0) , __FUNCTION__ , 257 "cannot access boot record\n" ); 317 258 318 259 #if CONFIG_FATFS_DEBUG … … 336 277 uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 ); 337 278 338 assert( (sector_size == 512) , __FUNCTION__ , "sector size must be 512 bytes" ); 279 nolock_assert( (sector_size == 512) , __FUNCTION__ , 280 "sector size must be 512 bytes\n" ); 339 281 340 282 // check cluster size from boot record 341 283 uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 ); 342 284 343 assert( (nb_sectors == 8) , __FUNCTION__ , "cluster size must be 8 sectors" ); 285 nolock_assert( (nb_sectors == 8) , __FUNCTION__ , 286 "cluster size must be 8 sectors\n" ); 344 287 345 288 // check number of FAT copies from boot record 346 289 uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 ); 347 290 348 assert( (nb_fats == 1) , __FUNCTION__ , "number of FAT copies must be 1" ); 291 nolock_assert( (nb_fats == 1) , __FUNCTION__ , 292 "number of FAT copies must be 1\n" ); 349 293 350 294 // get & check number of sectors in FAT from boot record 351 295 uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 ); 352 296 353 assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , "FAT not multiple of 16 sectors"); 297 nolock_assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , 298 "FAT not multiple of 16 sectors\n"); 354 299 355 300 // get and check root cluster from boot record 356 301 uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 ); 357 302 358 assert( (root_cluster == 2) , __FUNCTION__ , "Root cluster index must be 2"); 303 nolock_assert( (root_cluster == 2) , __FUNCTION__ , 304 "root cluster index must be 2\n"); 359 305 360 306 // get FAT lba from boot record … … 375 321 fatfs_ctx->fat_sectors_count = fat_sectors; 376 322 fatfs_ctx->bytes_per_sector = sector_size; 377 fatfs_ctx-> bytes_per_cluster = sector_size *nb_sectors;323 fatfs_ctx->sectors_per_cluster = nb_sectors; 378 324 fatfs_ctx->cluster_begin_lba = fat_lba + fat_sectors; 379 325 fatfs_ctx->root_dir_cluster = 2; … … 396 342 fatfs_ctx->fat_mapper_xp ); 397 343 398 // initialize the VFS context399 vfs_ctx->type = FS_TYPE_FATFS;400 vfs_ctx->attr = 0; // not READ_ONLY / not SYNC401 vfs_ctx->count = fat_sectors << 10; // total number of sectors in data region402 vfs_ctx->blksize = 512; // number of bytes per sector403 vfs_ctx->root_xp = root_inode_xp;404 vfs_ctx->extend = fatfs_ctx;405 406 spinlock_init( &vfs_ctx->lock );407 408 bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );409 410 return 0;411 412 344 } // end fatfs_ctx_init() 413 414 415 416 //////////////////////////////////////////////////// 417 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx ) 345 346 ///////////////////////////////////////////////// 347 void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx ) 418 348 { 419 349 kmem_req_t req; 420 fatfs_ctx_t * fatfs_ctx; 421 422 // get pointer on FATFS context extension 423 fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 424 425 req.type = KMEM_FATFS_INODE; 350 req.type = KMEM_FATFS_CTX; 426 351 req.ptr = fatfs_ctx; 427 352 kmem_free( &req ); 428 353 } 429 430 431 ////////////////////////////////////////////////////432 error_t fatfs_inode_create( vfs_inode_t * vfs_inode,433 uint32_t first_cluster )434 {435 kmem_req_t req;436 fatfs_inode_t * fatfs_inode;437 438 // allocate memory for FATFS inode extension439 req.type = KMEM_FATFS_INODE;440 req.size = sizeof(fatfs_inode_t);441 req.flags = AF_KERNEL | AF_ZERO;442 fatfs_inode = (fatfs_inode_t *)kmem_alloc( &req );443 444 if( fatfs_inode == NULL ) return ENOMEM;445 446 // link FATFS inode to VFS inode447 vfs_inode->extend = fatfs_inode;448 449 // initialise FATFS inode450 fatfs_inode->first_cluster = first_cluster;451 452 return 0;453 }454 455 ///////////////////////////////////////////////////456 void fatfs_inode_destroy( vfs_inode_t * vfs_inode )457 {458 kmem_req_t req;459 fatfs_inode_t * fatfs_inode;460 461 // get pointer on FATFS inode462 fatfs_inode = (fatfs_inode_t *)vfs_inode->extend;463 464 req.type = KMEM_FATFS_INODE;465 req.ptr = fatfs_inode;466 kmem_free( &req );467 468 vfs_inode->extend = NULL;469 }470 471 354 472 355 //////////////////////////////////////////////// … … 484 367 vfs_inode_t * vfs_inode = mapper->inode; 485 368 486 // get FATFS inode pointer for VFS inode 487 fatfs_inode_t * fatfs_inode = (fatfs_inode_t *)vfs_inode->extend; 488 489 // get first cluster index from FATFS inode 490 uint32_t first_cluster = fatfs_inode->first_cluster; 491 492 // get FATFS context pointer from FATFS inode 493 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_inode->ctx->extend; 369 // get first cluster index from VFS inode 370 uint32_t first_cluster = (uint32_t)(intptr_t)vfs_inode->extend; 371 372 // get FATFS context pointer from VFS context 373 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend; 494 374 495 375 // get number of sectors -
trunk/kernel/vfs/fatfs.h
r23 r188 160 160 typedef struct fatfs_ctx_s 161 161 { 162 uint32_t fat_sectors_count; /*! number of sectors in FAT region */ 163 uint32_t bytes_per_sector; /*! number of bytes per sector */ 164 uint32_t sectors_per_cluster; /*! number of sectors per cluster */ 162 165 uint32_t fat_begin_lba; /*! lba of FAT region */ 163 uint32_t fat_sectors_count; /*! number of sectors in FAT region */164 uint32_t bytes_per_sector; /*! */165 uint32_t bytes_per_cluster; /*! */166 166 uint32_t cluster_begin_lba; /*! lba of data region */ 167 uint32_t sectors_per_cluster; /*! cluster index for root directory */ 168 uint32_t root_dir_cluster; /*! */ 167 uint32_t root_dir_cluster; /*! cluster index for the root directory */ 169 168 uint32_t last_allocated_sector; /*! TODO ??? */ 170 169 uint32_t last_allocated_index; /*! TODO ??? */ … … 173 172 fatfs_ctx_t; 174 173 175 /*****************************************************************************************176 * This structure defines the FATFS specific inode (extension to VFS inode).177 ****************************************************************************************/178 179 typedef struct fatfs_inode_s180 {181 uint32_t first_cluster; /*! first cluster for this file/dir */182 }183 fatfs_inode_t;184 185 186 187 188 174 ////////////////////////////////////////////////////////////////////////////////////////// 189 // These functions are specific to the FATFS, and cannot be called by the VFS. 175 // Generic API: These functions are called by the kernel, 176 // and must be implemented by all File Systems. 190 177 ////////////////////////////////////////////////////////////////////////////////////////// 191 178 192 /***************************************************************************************** 193 * This function returns the LBA of the first sector of a FAT cluster. 194 * This function can be called by any thread running in any cluster. 195 ***************************************************************************************** 196 * @ ctx : pointer on FATFS context. 197 * @ cluster : cluster index in FATFS. 198 * @ return the lba value. 199 ****************************************************************************************/ 200 inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx, 201 uint32_t cluster ); 179 /****************************************************************************************** 180 * This fuction allocates memory from local cluster for a FATFS context descriptor. 181 ****************************************************************************************** 182 * @ return a pointer on the created context / return NULL if failure. 183 *****************************************************************************************/ 184 fatfs_ctx_t * fatfs_ctx_alloc(); 185 186 /***************************************************************************************** 187 * This function access the external boot device, and initialises it 188 * from informations contained in the boot record. 189 ***************************************************************************************** 190 * @ vfs_ctx : local pointer on VFS context for FATFS. 191 ****************************************************************************************/ 192 void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx ); 193 194 /***************************************************************************************** 195 * This function releases memory dynamically allocated for the FATFS context extension. 196 ***************************************************************************************** 197 * @ vfs_ctx : local pointer on VFS context. 198 ****************************************************************************************/ 199 void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx ); 200 201 /***************************************************************************************** 202 * This function moves a page from the mapper to the FATFS file system on device. 203 * It must be called by a thread running in cluster containing the mapper. 204 * The pointer on the mapper and the page index in file are registered 205 * in the page descriptor. 206 ***************************************************************************************** 207 * @ page : local pointer on page descriptor. 208 * @ return 0 if success / return EIO if error. 209 ****************************************************************************************/ 210 error_t fatfs_write_page( struct page_s * page ); 211 212 /***************************************************************************************** 213 * This function moves a page from the FATFS file system on device to the mapper. 214 * It must be called by a thread running in cluster containing the mapper. 215 * The pointer on the mapper and the page index in file are registered 216 * in the page descriptor. 217 ***************************************************************************************** 218 * @ page : local pointer on page descriptor. 219 * @ return 0 if success / return EIO if error. 220 ****************************************************************************************/ 221 error_t fatfs_read_page( struct page_s * page ); 202 222 203 223 /***************************************************************************************** … … 214 234 * automatically updates the FAT mapper from informations stored on device in case of miss. 215 235 ***************************************************************************************** 216 * @ mapper : local pointer on the FAT mapper.217 * @ first : index of the first FATFS cluster allocated to the file.218 * @ page: index of searched page in the file.219 * @ cluster : [out] pointer on buffer for the found FATFS cluster index.236 * @ mapper : local pointer on the FAT mapper. 237 * @ first_cluster : index of the first FATFS cluster allocated to the file. 238 * @ searched_page : index of searched page in the file. 239 * @ cluster : [out] pointer on buffer for the found FATFS cluster index. 220 240 * @ return 0 if success / return EIO if FAT mapper miss cannot be solved. 221 241 ****************************************************************************************/ … … 223 243 uint32_t first_cluster, 224 244 uint32_t searched_page, 225 uint32_t * cluster ); 226 227 228 229 230 ////////////////////////////////////////////////////////////////////////////////////////// 231 // These functions are called by the VFS, and must be implemented by all File Systems. 232 ////////////////////////////////////////////////////////////////////////////////////////// 233 234 /****************************************************************************************** 235 * This function initializes the FATFS file system as the root FS. 236 * It is executed cooperatively during kernel init by all CP0s in all clusters. 237 * The initilisation is made in three phases, separated by synchronisation barrier: 238 * - phase 1 : all CP0s in all clusters allocate memory for the local copy of 239 * the FATFS context. 240 * - phase 2 : cluster_0 only creates the root inode descriptor, access the external 241 * device to get information stored on the boot record, and initialises both 242 * the VFS context, and the FATFS context. 243 * - phase 3 : all other clusters initialize their local VFS context and FATFS context 244 * from values contained in cluster_0, using hal_remote_memcpy(). 245 ****************************************************************************************** 246 * @ return an extended pointer on the created root inode / return XPTR_NULL if failure. 247 *****************************************************************************************/ 248 xptr_t fatfs_init(); 249 250 /****************************************************************************************** 251 * This function mount the FATFS on the root FS. 252 * TODO not implemented [AG] 253 ****************************************************************************************** 254 * @ parent_inode_xp : extended pointer on the parent inode. 255 *****************************************************************************************/ 256 error_t fatfs_mount( xptr_t parent_inode_xp ); 257 258 259 /***************************************************************************************** 260 * This function initializes both the VFS context and the FATFS context. 261 * Both the VFS context and the FATFS context must have been previously allocated. 262 * It access the device to read the boot record, and is supposed to be called only 263 * in cluster_0 (in other clusters these contexts are replicated from values 264 * contained in cluster_0). 265 ***************************************************************************************** 266 * @ vfs_ctx : local pointer on VFS context for FATFS. 267 * @ fatfs_ctx : local pointer on specific FATFS context. 268 * @ root_inode_xp : extended pointer on VFS root inode. 269 ****************************************************************************************/ 270 error_t fatfs_ctx_init( struct vfs_ctx_s * vfs_ctx, 271 struct fatfs_ctx_s * fatfs_ctx, 272 xptr_t root_inode_xp ); 273 274 /***************************************************************************************** 275 * This function releases memory dynamically allocated for the FATFS context extension. 276 ***************************************************************************************** 277 * @ vfs_ctx : local pointer on VFS context. 278 ****************************************************************************************/ 279 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx ); 280 281 282 283 /***************************************************************************************** 284 * This function allocates memory for a FATFS inode, initializes it, 285 * and link it to the VFS inode. 286 ***************************************************************************************** 287 * @ inode : local pointer on the VFS inode. 288 * @ first_cluster : first cluster index in the FAT32. 289 * @ return 0 if success / return ENOMEM if error. 290 ****************************************************************************************/ 291 error_t fatfs_inode_create( struct vfs_inode_s * inode, 292 uint32_t first_cluster); 293 294 /***************************************************************************************** 295 * This function releases memory allocated for a FATFS inode. 296 ***************************************************************************************** 297 * @ inode : local pointer on vfs_inode. 298 ****************************************************************************************/ 299 void fatfs_inode_destroy( struct vfs_inode_s * inode ); 300 301 302 303 /***************************************************************************************** 304 * This function moves a page from the mapper to the FATFS file system on device. 305 * It must be called by a thread running in cluster containing the mapper. 306 * The pointer on the mapper and the page index in file are registered 307 * in the page descriptor. 308 ***************************************************************************************** 309 * @ page : local pointer on page descriptor. 310 * @ return 0 if success / return EIO if error. 311 ****************************************************************************************/ 312 error_t fatfs_write_page( struct page_s * page ); 313 314 /***************************************************************************************** 315 * This function moves a page from the FATFS file system on device to the mapper. 316 * It must be called by a thread running in cluster containing the mapper. 317 * The pointer on the mapper and the page index in file are registered 318 * in the page descriptor. 319 ***************************************************************************************** 320 * @ page : local pointer on page descriptor. 321 * @ return 0 if success / return EIO if error. 322 ****************************************************************************************/ 323 error_t fatfs_read_page( struct page_s * page ); 324 325 326 245 uint32_t * cluster ); 327 246 328 247 #endif /* _FATFS_H_ */ -
trunk/kernel/vfs/ramfs.c
r23 r188 32 32 33 33 34 35 36 37 ///////////////////////////////////////////////////////////////////////////////////////38 // The following functions are called by the VFS.39 ///////////////////////////////////////////////////////////////////////////////////////40 41 34 ////////////////////////////////////////////// 42 35 error_t ramfs_mount( xptr_t parent_inode_xp, 43 36 char * ramfs_root_name ) 44 37 { 45 xptr_t 38 xptr_t root_inode_xp; // unused 46 39 40 cxy_t cxy = vfs_cluster_random_select(); 41 47 42 // create VFS dentry and VFS inode for RAMFS root directory 48 return vfs_add_child_in_parent( INODE_TYPE_DIR, 43 return vfs_add_child_in_parent( cxy, 44 INODE_TYPE_DIR, 49 45 FS_TYPE_RAMFS, 50 46 parent_inode_xp, 51 47 ramfs_root_name, 48 NULL, 52 49 &root_inode_xp ); 53 50 } 54 51 55 56 ////////////////////////////////////////////57 error_t ramfs_ctx_init( vfs_ctx_t * vfs_ctx,58 xptr_t root_inode_xp )59 60 {61 vfs_ctx->type = FS_TYPE_RAMFS;62 vfs_ctx->attr = 0; // not READ_ONLY / not SYNC63 vfs_ctx->count = 0; // unused for RAMFS64 vfs_ctx->blksize = 512; // unused for RAMFS65 vfs_ctx->root_xp = root_inode_xp;66 vfs_ctx->extend = NULL; // unused for DEVFS67 68 spinlock_init( &vfs_ctx->lock );69 70 bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );71 72 return 0;73 }74 -
trunk/kernel/vfs/ramfs.h
r23 r188 27 27 28 28 /////////////////////////////////////////////////////////////////////////////////////////// 29 // The RAMFS File System Rdoes not uses any external device to store data.29 // The RAMFS File System does not uses any external device to store data. 30 30 // It stores the dynamically created files and directories in the VFS mappers. 31 31 // The ramfs_read_page() and ramfs_write_page() functions should never be used. 32 // The RAMFS cannot be used as the root FS. 32 // The RAMFS cannot be used as the root File System. 33 // 33 34 // There is no RAMFS context extension, and no RAMFS inode extension. 34 35 /////////////////////////////////////////////////////////////////////////////////////////// 35 36 36 37 37 /**** Forward declarations ****/38 39 40 //////////////////////////////////////////////////////////////////////////////////////////41 // These functions are called by the VFS, and must be implemented by all FS.42 //////////////////////////////////////////////////////////////////////////////////////////43 44 /******************************************************************************************45 * This function does not exist, as the RAMFS cannot be the root FS.46 *****************************************************************************************/47 xptr_t ramfs_init();48 38 49 39 /****************************************************************************************** … … 52 42 * and create a new VFS inode in another cluster. 53 43 ****************************************************************************************** 54 * @ parent_inode_xp : extended pointer on the parent inode .44 * @ parent_inode_xp : extended pointer on the parent inode in VFS. 55 45 * @ ramfs_root_name : RAMFS root directory name. 56 46 *****************************************************************************************/ … … 58 48 char * ramfs_root_name ); 59 49 60 /*****************************************************************************************61 * This function initializes all fields of the VFS context.62 * No extra memory is allocated for a RAMFS context.63 ****************************************************************************************/64 error_t ramfs_ctx_init( struct vfs_ctx_s * vfs_ctx,65 xptr_t root_inode_xp );66 67 /*****************************************************************************************68 * This function does not exist for a RAMFS context, as there is no RAMFS context.69 ****************************************************************************************/70 error_t ramfs_ctx_destroy();71 72 /*****************************************************************************************73 * This function does not exist, as the RAMFS does not use a RAMFS inode extension.74 ****************************************************************************************/75 error_t ramfs_inode_create( struct vfs_inode_s * inode );76 77 /*****************************************************************************************78 * This function does not exist, as the RAMFS does not use a RAMFS inode extension.79 ****************************************************************************************/80 void ramfs_inode_destroy( struct vfs_inode_s * inode );81 82 /*****************************************************************************************83 * This function does nothing for the RAMFS File System.84 ****************************************************************************************/85 error_t ramfs_write_page( struct page_s * page );86 87 /*****************************************************************************************88 * This function does not exist for the RAMFS File System.89 ****************************************************************************************/90 error_t ramfs_read_page( struct page_s * page );91 92 93 50 #endif /* _RAMFS_H_ */ -
trunk/kernel/vfs/vfs.c
r124 r188 52 52 ////////////////////////////////////////////////////////////////////////////////////////// 53 53 54 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocate in kernel_init.c 54 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in kernel_init.c 55 55 56 56 57 ////////////////////////////////////////////////////////////////////////////////////////// 57 58 // Context related functions 58 59 ////////////////////////////////////////////////////////////////////////////////////////// 60 61 //////////////////////////////////////// 62 void vfs_ctx_init( vfs_fs_type_t type, 63 uint32_t attr, 64 uint32_t total_clusters, 65 uint32_t cluster_size, 66 xptr_t vfs_root_xp, 67 void * extend ) 68 { 69 vfs_ctx_t * vfs_ctx = &fs_context[type]; 70 71 vfs_ctx->type = type; 72 vfs_ctx->attr = attr; 73 vfs_ctx->total_clusters = total_clusters; 74 vfs_ctx->cluster_size = cluster_size; 75 vfs_ctx->vfs_root_xp = vfs_root_xp; 76 vfs_ctx->extend = extend; 77 78 spinlock_init( &vfs_ctx->lock ); 79 80 bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) ); 81 } 59 82 60 83 //////////////////////////////////////////// … … 101 124 ////////////////////////////////////////////////////////////////////////////////////////// 102 125 126 char * vfs_inode_type_str( uint32_t type ) 127 { 128 if ( type == INODE_TYPE_FILE ) return "FILE"; 129 else if( type == INODE_TYPE_DIR ) return "DIR "; 130 else if( type == INODE_TYPE_FIFO ) return "FIFO"; 131 else if( type == INODE_TYPE_PIPE ) return "PIPE"; 132 else if( type == INODE_TYPE_SOCK ) return "SOCK"; 133 else if( type == INODE_TYPE_DEV ) return "DEV "; 134 else if( type == INODE_TYPE_SYML ) return "SYML"; 135 else return "undefined"; 136 } 137 103 138 ////////////////////////////////////////////////////// 104 105 139 error_t vfs_inode_create( xptr_t dentry_xp, 106 140 vfs_fs_type_t fs_type, 107 141 vfs_inode_type_t inode_type, 142 void * extend, 108 143 uint32_t attr, 109 144 uint32_t rights, … … 175 210 inode->ctx = ctx; 176 211 inode->mapper = NULL; 212 inode->extend = extend; 177 213 178 214 // initialise threads waiting queue … … 307 343 kmem_req_t req; // request to kernel memory allocator 308 344 309 // check type andget pointer on context345 // get pointer on context 310 346 if ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; 311 347 else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; … … 349 385 xhtab_insert( XPTR( local_cxy , &parent->children ), 350 386 name, 351 XPTR( local_cxy , &dentry-> xlist ) );387 XPTR( local_cxy , &dentry->list ) ); 352 388 353 389 // return extended pointer on dentry … … 372 408 kmem_free( &req ); 373 409 } 410 374 411 375 412 … … 797 834 798 835 799 ///////////////////////////////////////////////////////////////////////////////////////// r836 ////////////////////////////////////////////////////////////////////////////////////////// 800 837 // Inode Tree functions 801 838 ////////////////////////////////////////////////////////////////////////////////////////// 839 840 ///////////////////////////////// 841 cxy_t vfs_cluster_random_select() 842 { 843 uint32_t x_size = LOCAL_CLUSTER->x_size; 844 uint32_t y_size = LOCAL_CLUSTER->y_size; 845 uint32_t y_width = LOCAL_CLUSTER->y_width; 846 uint32_t index = ( hal_get_cycles() + hal_get_gid() ) % (x_size * y_size); 847 uint32_t x = index / y_size; 848 uint32_t y = index % y_size; 849 850 return (x<<y_width) + y; 851 } 852 853 854 ////////////////////////////////////////////////////////////////////////// 855 // This static function is called by the vfs_display() function. 856 ////////////////////////////////////////////////////////////////////////// 857 static void vfs_recursive_display( xptr_t inode_xp, 858 xptr_t name_xp, 859 uint32_t indent ) 860 { 861 cxy_t inode_cxy; 862 vfs_inode_t * inode_ptr; 863 vfs_inode_type_t inode_type; 864 xptr_t inode_children_xp; // extended pointer on children xhtab 865 866 xptr_t dentry_xp; 867 cxy_t dentry_cxy; 868 vfs_dentry_t * dentry_ptr; 869 870 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 871 872 xptr_t child_inode_xp; 873 xptr_t dentry_name_xp; 874 875 char * indent_str[] = { "", // level 0 876 " ", // level 1 877 " ", // level 2 878 " ", // level 3 879 " ", // level 4 880 " ", // level 5 881 " ", // level 6 882 " ", // level 7 883 " ", // level 8 884 " ", // level 9 885 " ", // level 10 886 " ", // level 11 887 " ", // level 12 888 " ", // level 13 889 " ", // level 14 890 " " }; // level 15 891 892 assert( (inode_xp != XPTR_NULL) , __FUNCTION__ , "inode_xp cannot be NULL\n" ); 893 assert( (name_xp != XPTR_NULL) , __FUNCTION__ , "name_xp cannot be NULL\n" ); 894 assert( (indent < 16) , __FUNCTION__ , "depth cannot be larger than 15\n" ); 895 896 // get inode cluster and local pointer 897 inode_cxy = GET_CXY( inode_xp ); 898 inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp ); 899 900 // get inode type 901 inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) ); 902 903 // make a local copy of node name 904 hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp ); 905 906 // display inode 907 printk(" %s %s : %s\n", indent_str[indent], vfs_inode_type_str( inode_type ), name ); 908 909 // scan directory entries 910 if( inode_type == INODE_TYPE_DIR ) 911 { 912 // get extended pointer on directory entries xhtab 913 inode_children_xp = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->children ) ); 914 915 // get xhtab lock 916 xhtab_read_lock( inode_children_xp ); 917 918 // get first dentry from xhtab 919 dentry_xp = xhtab_get_first( inode_children_xp ); 920 921 while( dentry_xp != XPTR_NULL ) 922 { 923 // get dentry cluster and local pointer 924 dentry_cxy = GET_CXY( dentry_xp ); 925 dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp ); 926 927 // get extended pointer on child inode 928 child_inode_xp = hal_remote_lwd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) ); 929 930 // get extended pointer on dentry name 931 dentry_name_xp = XPTR( dentry_cxy , &dentry_ptr->name ); 932 933 // recursive call on child inode 934 vfs_recursive_display( child_inode_xp , dentry_name_xp , indent+1 ); 935 936 // get next dentry 937 dentry_xp = xhtab_get_next( inode_children_xp ); 938 } 939 940 // release xhtab lock 941 xhtab_read_unlock( inode_children_xp ); 942 } 943 } // end vfs_recursive_display() 944 945 /////////////////////////////////// 946 void vfs_display( xptr_t inode_xp ) 947 { 948 xptr_t name_xp; // extended pointer on string containing the inode name 949 xptr_t dentry_xp; 950 cxy_t dentry_cxy; 951 vfs_dentry_t * dentry_ptr; 952 953 printk("\n@@@ %s enters\n", __FUNCTION__ ); 954 955 // get target inode cluster and local pointer 956 cxy_t inode_cxy = GET_CXY( inode_xp ); 957 vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp ); 958 959 // get extended pointer on associated dentry 960 dentry_xp = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 961 962 // check if target inode is the File System root 963 if( dentry_xp == XPTR_NULL ) 964 { 965 // build extended pointer on root name 966 name_xp = XPTR( local_cxy , "/" ); 967 } 968 else 969 { 970 // get dentry cluster and local pointer 971 dentry_cxy = GET_CXY( dentry_xp ); 972 dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp ); 973 974 // get extended pointer on dentry name 975 name_xp = XPTR( dentry_cxy , &dentry_ptr->name ); 976 } 977 978 // print header 979 printk("\n*** Current VFS content ***\n"); 980 981 // call recursive function 982 vfs_recursive_display( inode_xp , name_xp , 0 ); 983 984 } // end vfs_diplay() 802 985 803 986 ////////////////////////////////////////////////////////////////////////////////////////// … … 913 1096 return 0; 914 1097 } 915 1098 916 1099 ////////////////////////////////////////////// 917 1100 error_t vfs_lookup( xptr_t cwd_xp, … … 993 1176 else inode_type = INODE_TYPE_FILE; 994 1177 995 // insert a child dentry/inode in parent inode 996 error = vfs_add_child_in_parent( inode_type, 1178 // select a cluster for child inode 1179 cxy_t child_cxy = vfs_cluster_random_select(); 1180 1181 // insert a new child dentry/inode in parent inode 1182 error = vfs_add_child_in_parent( child_cxy, 1183 inode_type, 997 1184 fs_type, 998 1185 parent_xp, 1186 NULL, // fs_type_specific inode extend 999 1187 name, 1000 1188 &child_xp ); … … 1002 1190 if( error ) 1003 1191 { 1004 printk("\n[ERROR] in %s : inode %s not found in path %s\n",1192 printk("\n[ERROR] in %s : node %s not found in path %s\n", 1005 1193 __FUNCTION__ , name , pathname ); 1006 1194 return ENOENT; … … 1024 1212 // } 1025 1213 1026 printk("\n@@@ bloup 0 : parent lock owner = %l / child lock owner = %l\n", 1027 vfs_inode_owner( parent_xp ) , vfs_inode_owner( child_xp ) ); 1214 // TODO TODO TODO access device and load inode mapper if required... 1028 1215 1029 1216 // take lock on child inode if not last 1030 1217 if( last == false ) vfs_inode_lock( child_xp ); 1031 1218 1032 printk("\n@@@ bloup 1\n");1033 1034 1219 // release lock on parent inode 1035 1220 vfs_inode_unlock( parent_xp ); 1036 1037 printk("\n@@@ bloup 2\n");1038 1221 1039 1222 // update loop variables … … 1060 1243 1061 1244 } // end vfs_lookup() 1062 1063 1245 1064 1246 //////////////////////////////////////////// … … 1131 1313 } // end vfs_get_path() 1132 1314 1133 /////////////////////////////////////////////////////////////// 1134 error_t vfs_add_child_in_parent( vfs_inode_type_t inode_type, 1315 1316 ////////////////////////////////////////////////////////////// 1317 error_t vfs_add_child_in_parent( cxy_t child_cxy, 1318 vfs_inode_type_t inode_type, 1135 1319 vfs_fs_type_t fs_type, 1136 1320 xptr_t parent_xp, 1137 1321 char * name, 1322 void * extend, 1138 1323 xptr_t * child_xp ) 1139 1324 { … … 1174 1359 printk("\n[ERROR] in %s : cannot create dentry in cluster %x\n", 1175 1360 __FUNCTION__ , parent_cxy ); 1176 1177 1361 return error; 1178 1362 } 1179 1363 1180 // select a target cluster for child inode1181 uint32_t x_size = LOCAL_CLUSTER->x_size;1182 uint32_t y_size = LOCAL_CLUSTER->y_size;1183 uint32_t y_width = LOCAL_CLUSTER->y_width;1184 uint32_t index = ( hal_get_cycles() + hal_get_gid() ) % (x_size * y_size);1185 uint32_t x = index / y_size;1186 uint32_t y = index % y_size;1187 cxy_t child_cxy = (x<<y_width) + y;1188 1189 1364 // create child inode TODO : define attr / mode / uid / gid 1190 1365 uint32_t attr = 0; … … 1198 1373 fs_type, 1199 1374 inode_type, 1375 extend, 1200 1376 attr, 1201 1377 mode, … … 1210 1386 fs_type, 1211 1387 inode_type, 1388 extend, 1212 1389 attr, 1213 1390 mode, -
trunk/kernel/vfs/vfs.h
r101 r188 132 132 vfs_fs_type_t type; /*! File System type */ 133 133 uint32_t attr; /*! global attributes for all files in FS */ 134 uint32_t count;/*! total number of clusters on device */135 uint32_t blksize; /*! device cluster size (bytes)*/136 xptr_t root_xp; /*! extended pointer on root inode*/134 uint32_t total_clusters; /*! total number of clusters on device */ 135 uint32_t cluster_size; /*! cluster size on device (bytes) */ 136 xptr_t vfs_root_xp; /*! extended pointer on VFS root inode */ 137 137 spinlock_t lock; /*! lock protecting inum allocator */ 138 138 uint32_t bitmap[BITMAP_SIZE(CONFIG_VFS_MAX_INODES)]; /* inum allocator */ … … 160 160 typedef enum 161 161 { 162 INODE_TYPE_FILE = 0x001, /*! file*/163 INODE_TYPE_DIR = 0x002, /*! directory*/164 INODE_TYPE_FIFO = 0x004, /*! POSIX named pipe*/165 INODE_TYPE_PIPE = 0x008, /*! POSIX anonymous pipe*/166 INODE_TYPE_SOCK ET = 0x010, /*! POSIX socket*/167 INODE_TYPE_DEV = 0x020, /*! character peripheral channel*/168 INODE_TYPE_SYML = 0x080, /*! symbolic link*/162 INODE_TYPE_FILE = 0x001, /*! file */ 163 INODE_TYPE_DIR = 0x002, /*! directory */ 164 INODE_TYPE_FIFO = 0x004, /*! POSIX named pipe */ 165 INODE_TYPE_PIPE = 0x008, /*! POSIX anonymous pipe */ 166 INODE_TYPE_SOCK = 0x010, /*! POSIX socket */ 167 INODE_TYPE_DEV = 0x020, /*! device channel */ 168 INODE_TYPE_SYML = 0x080, /*! symbolic link */ 169 169 } 170 170 vfs_inode_type_t; … … 182 182 typedef struct vfs_inode_s 183 183 { 184 struct vfs_ctx_s * ctx; /*! local pointer on FS context */ 185 uint32_t gc; /*! generation counter */ 186 uint32_t inum; /*! inode identifier (unique in file system) */ 187 uint32_t attr; /*! inode attributes (see above) */ 188 vfs_inode_type_t type; /*! inode type (see above) */ 189 uint32_t size; /*! number of bytes */ 190 uint32_t links; /*! number of alias dentry */ 191 uid_t uid; /*! user owner identifier */ 192 gid_t gid; /*! group owner identifier */ 193 uint32_t rights; /*! access rights */ 194 uint32_t refcount; /*! reference counter (all pointers) */ 195 xptr_t parent_xp; /*! extended pointer on parent dentry */ 196 xhtab_t children; /*! embedded xhtab of vfs_dentry_t */ 197 remote_rwlock_t data_lock; /*! protect read/write to data and to size */ 198 remote_spinlock_t main_lock; /*! protect inode tree traversal and modifs */ 199 list_entry_t list; /*! member of set of inodes in same cluster */ 200 xlist_entry_t wait_root; /*! root of threads waiting on this inode */ 201 struct vfs_inode_op_s * op; /*! TODO ??? */ 202 struct mapper_s * mapper; /*! associated file cache */ 203 void * extend; /*! FS specific inode extension */ 184 struct vfs_ctx_s * ctx; /*! local pointer on FS context */ 185 uint32_t gc; /*! generation counter */ 186 uint32_t inum; /*! inode identifier (unique in file system) */ 187 uint32_t attr; /*! inode attributes (see above) */ 188 vfs_inode_type_t type; /*! inode type (see above) */ 189 uint32_t size; /*! number of bytes */ 190 uint32_t links; /*! number of alias dentry */ 191 uid_t uid; /*! user owner identifier */ 192 gid_t gid; /*! group owner identifier */ 193 uint32_t rights; /*! access rights */ 194 uint32_t refcount; /*! reference counter (all pointers) */ 195 xptr_t parent_xp; /*! extended pointer on parent dentry */ 196 xhtab_t children; /*! embedded xhtab of children dentries */ 197 remote_rwlock_t data_lock; /*! protect read/write to data and to size */ 198 remote_spinlock_t main_lock; /*! protect inode tree traversal and modifs */ 199 list_entry_t list; /*! member of set of inodes in same cluster */ 200 xlist_entry_t wait_root; /*! root of threads waiting on this inode */ 201 struct mapper_s * mapper; /*! associated file cache */ 202 void * extend; /*! fs_type_specific inode extension */ 204 203 } 205 204 vfs_inode_t; … … 214 213 typedef struct vfs_dentry_s 215 214 { 216 struct vfs_ctx_s * ctx; /*! local pointer on FS context */ 217 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 218 uint32_t length; /*! name length (bytes) */ 219 uint32_t refcount; /*! reference counter (all pointers) */ 220 struct vfs_inode_s * parent; /*! local pointer on parent inode */ 221 xptr_t child_xp; /*! extended pointer on child inode */ 222 xlist_entry_t xlist; /*! member of xlist of dentries with same key */ 223 struct vfs_dentry_op_s * op; /*! TODO */ 224 void * extend; /*! FS specific extension */ 215 struct vfs_ctx_s * ctx; /*! local pointer on FS context */ 216 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 217 uint32_t length; /*! name length (bytes) */ 218 uint32_t refcount; /*! reference counter (all pointers) */ 219 struct vfs_inode_s * parent; /*! local pointer on parent inode */ 220 xptr_t child_xp; /*! extended pointer on child inode */ 221 xlist_entry_t list; /*! member of list of dentries with same key */ 222 void * extend; /*! FS specific extension */ 225 223 } 226 224 vfs_dentry_t; … … 231 229 * the inode, when a thread makes an open() or opendir() system call. 232 230 * It cannot exist a file structure without an inode structure. 233 * Aa the fd_array (containing extended pointers on the open file descriptors) 231 * Aa the fd_array (containing extended pointers on the open file descriptors)* is replicated in all process descriptors, we need a references counter. 234 232 * is replicated in all process descriptors, we need a references counter. 235 233 *****************************************************************************************/ … … 313 311 314 312 /*****************************************************************************************/ 315 /******************* FS Context related functions ****************************************/ 316 /*****************************************************************************************/ 313 /******************* VFS Context related functions ****************************************/ 314 /*****************************************************************************************/ 315 316 /****************************************************************************************** 317 * This function initialise a (statically allocated) VFS context in local cluster. 318 ****************************************************************************************** 319 * @ fs_type : file system type. 320 * @ attr : global attributes (for all files in FS. 321 * @ total_clusters : total number of clusters on device. 322 * @ cluster_size : cluster size on device (bytes). 323 * @ vfs_root_xp : extended pointer on VFS root inode. 324 * @ extend : fs_type_specific extension. 325 *****************************************************************************************/ 326 void vfs_ctx_init( vfs_fs_type_t type, 327 uint32_t attr, 328 uint32_t total_clusters, 329 uint32_t cluster_size, 330 xptr_t vfs_root_xp, 331 void * extend ); 317 332 318 333 /****************************************************************************************** … … 355 370 * @ fs_type : file system type. 356 371 * @ inode_type : inode type. 372 * @ extend : local pointer on vs_type_specific extension. 357 373 * @ attr : inode attributes. 358 374 * @ rights : inode access rights. … … 365 381 vfs_fs_type_t fs_type, 366 382 vfs_inode_type_t inode_type, 383 void * extend, 367 384 uint32_t attr, 368 385 uint32_t rights, … … 550 567 /******************* Inode-Tree related functions ****************************************/ 551 568 /*****************************************************************************************/ 569 570 /****************************************************************************************** 571 * This function randomly selects a cluster for a new inode. 572 ****************************************************************************************** 573 * @ returns the selected cluster identifier. 574 *****************************************************************************************/ 575 cxy_t vfs_cluster_random_select(); 552 576 553 577 /****************************************************************************************** … … 594 618 * uses the rpc_dentry_create_client() and rpc_inode_create client() if required. 595 619 * - The dentry is created in the cluster containing the existing <parent_xp> inode. 596 * - the child inode and its associated mapper are created in a randomly selected cluster.620 * - the inode and its associated mapper are created in cluster identified by <child_cxy>. 597 621 * - The new dentry name is defined by the <name> argument. 598 622 * - The new inode and the parent inode can have different FS types. 599 623 ****************************************************************************************** 624 * @ child_cxy : target cluster for child inode. 600 625 * @ inode_type : new inode type 601 626 * @ fs_type : new inode FS type. 602 627 * @ parent_xp : extended pointer on parent inode. 603 628 * @ name : new directory entry name. 629 * @ extend : fs_type_specific inode extension. 604 630 * @ child_xp : [out] buffer for extended pointer on child inode. 605 631 * @ return 0 if success / ENOENT if entry not found in parent directory 606 632 *****************************************************************************************/ 607 error_t vfs_add_child_in_parent( vfs_inode_type_t inode_type, 633 error_t vfs_add_child_in_parent( cxy_t child_cxy, 634 vfs_inode_type_t inode_type, 608 635 vfs_fs_type_t fs_type, 609 636 xptr_t parent_xp, 610 637 char * name, 638 void * extend, 611 639 xptr_t * child_xp ); 612 640 … … 620 648 error_t vfs_remove_child_from_parent( xptr_t child_xp ); 621 649 650 /****************************************************************************************** 651 * This recursive function diplays a complete inode/dentry sub-tree. 652 * Any inode can be selected as the sub-tree root. 653 * TODO this function is not ptotected against a concurrent node removal... 654 ****************************************************************************************** 655 * @ inode_xp : extended pointer on sub-tree root inode. 656 *****************************************************************************************/ 657 void vfs_display( xptr_t inode_xp ); 622 658 623 659
Note: See TracChangeset
for help on using the changeset viewer.