Changeset 295 for soft/giet_vm/giet_drivers
- Timestamp:
- Mar 26, 2014, 6:44:44 PM (11 years ago)
- Location:
- soft/giet_vm/giet_drivers
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/bdv_driver.c
r289 r295 10 10 // a single channel, block oriented, external storage contrÃŽler. 11 11 // 12 // It can exist only one block-device controler in the architecture. 13 // 14 // The _bdv_read() and _bdv_write() functions use the _bdv_access() function, 15 // that is always blocking, but can be called in 4 modes: 16 // 17 // - In BOOT_PA mode, the _bdv_access() function uses a polling policy on the 18 // IOC_STATUS register to detect transfer completion, as hardware interrupts 19 // are not activated. This mode is used by the boot code to load the map.bin 20 // file into memory. 21 // 22 // - In BOOT_VA mode, the _bdv_access() function uses a polling policy on 23 // IOC_STATUS register to detect transfer completion. This mode is used by 24 // the boot code to load the various .elf files into memory. 25 // 26 // - In KERNEL mode, the _bdv_access() function uses a descheduling strategy: 12 // The _bdv_read() and _bdv_write() functions are always blocking. 13 // They can be called in 3 modes: 14 // 15 // - In BOOT mode, these functions use a polling policy on the BDV STATUS 16 // register to detect transfer completion, as interrupts are not activated. 17 // This mode is used by the boot code to load the map.bin file into memory 18 // (before MMU activation), or to load the .elf files (after MMU activation). 19 // 20 // - In KERNEL mode, these functions use a descheduling strategy: 27 21 // The ISR executed when transfer completes should restart the calling task. 28 // There is no checking of user access right to the memory buffer. This mode29 // must be used to access IOC, for an "open" system call.30 // 31 // - In USER mode, the _bdv_access() function usesa descheduling strategy:22 // There is no checking of user access right to the memory buffer. 23 // This mode must be used, for an "open" system call. 24 // 25 // - In USER mode, these functions use a descheduling strategy: 32 26 // The ISR executed when transfer completes should restart the calling task, 33 27 // The user access right to the memory buffer must be checked. 34 // This mode must be used to access IOC,for a "read/write" system call.28 // This mode must be used for a "read/write" system call. 35 29 // 36 30 // As the BDV component can be used by several programs running in parallel, 37 // the _ ioc_lock variable guaranties exclusive access to the device. The31 // the _bdv_lock variable guaranties exclusive access to the device. The 38 32 // _bdv_read() and _bdv_write() functions use atomic LL/SC to get the lock. 39 33 // … … 47 41 // if the IOMMU is not activated. 48 42 // An error code is returned if these conditions are not verified. 49 /////////////////////////////////////////////////////////////////////////////////// 50 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file. 43 // 44 // The "seg_ioc_base" must be defined in giet_vsegs.ld file. 45 /////////////////////////////////////////////////////////////////////////////////// 46 // Implementation notes: 47 // 48 // 1. In order to share code, the two _bdv_read() and _bdv_write() functions 49 // call the same _bdv_access() function. 50 // 51 // 2. All accesses to BDV registers are done by the two 52 // _bdv_set_register() and _bdv_get_register() low-level functions, 53 // that are handling virtual / physical extended addressing. 51 54 /////////////////////////////////////////////////////////////////////////////////// 52 55 53 56 #include <giet_config.h> 57 #include <bdv_driver.h> 58 #include <xcu_driver.h> 54 59 #include <ioc_driver.h> 55 #include <bdv_driver.h>56 60 #include <utils.h> 57 61 #include <tty_driver.h> … … 59 63 60 64 /////////////////////////////////////////////////////////////////////////////// 61 // _bdv_access() 65 // BDV global variables 66 /////////////////////////////////////////////////////////////////////////////// 67 68 #define in_unckdata __attribute__((section (".unckdata"))) 69 70 in_unckdata unsigned int _bdv_lock = 0; 71 in_unckdata volatile unsigned int _bdv_status = 0; 72 in_unckdata volatile unsigned int _bdv_gtid; 73 74 /////////////////////////////////////////////////////////////////////////////// 75 // This low_level function returns the value contained in register (index). 76 /////////////////////////////////////////////////////////////////////////////// 77 unsigned int _bdv_get_register( unsigned int index ) 78 { 79 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + index; 80 return _io_extended_read( vaddr ); 81 } 82 83 /////////////////////////////////////////////////////////////////////////////// 84 // This low-level function set a new value in register (index). 85 /////////////////////////////////////////////////////////////////////////////// 86 void _bdv_set_register( unsigned int index, 87 unsigned int value ) 88 { 89 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + index; 90 _io_extended_write( vaddr, value ); 91 } 92 93 /////////////////////////////////////////////////////////////////////////////// 62 94 // This function transfer data between a memory buffer and the block device. 63 95 // The buffer lentgth is (count*block_size) bytes. … … 70 102 // Returns 0 if success, > 0 if error. 71 103 /////////////////////////////////////////////////////////////////////////////// 72 static unsigned int _bdv_access( unsigned int to_mem, 73 unsigned int mode, 74 unsigned int lba, 75 paddr_t buf_paddr, 76 unsigned int count) 77 { 78 79 #if GIET_DEBUG_IOC_DRIVER 80 _tty_get_lock( 0 ); 81 _puts("\n[IOC DEBUG] Enter _bdv_access() at cycle "); 82 _putd( _get_proctime() ); 83 _puts(" for processor "); 84 _putd( _get_procid() ); 85 _puts("\n - mode = "); 86 _putd( mode ); 87 _puts("\n - paddr = "); 88 _putx( buf_paddr ); 89 _puts("\n - sectors = "); 90 _putd( count ); 91 _puts("\n - lba = "); 92 _putx( lba ); 93 _puts("\n"); 94 _tty_release_lock( 0 ); 104 static unsigned int _bdv_access( unsigned int to_mem, 105 unsigned int mode, 106 unsigned int lba, 107 unsigned long long buf_paddr, 108 unsigned int count) 109 { 110 111 #if GIET_DEBUG_BDV_DRIVER 112 unsigned int procid = _get_procid(); 113 unsigned int cxy = procid / NB_PROCS_MAX; 114 unsigned int lpid = procid % NB_PROCS_MAX; 115 unsigned int x = cxy >> Y_WIDTH; 116 unsigned int y = cxy & ((1<<Y_WIDTH) - 1); 117 118 _printf("\n[BDV DEBUG] Processor[%d,%d,%d] enters _bdv_access() at cycle %d\n" 119 " - mode = %d\n" 120 " - paddr = %l\n" 121 " - sectors = %x\n" 122 " - lba = %x\n", 123 x, y, lpid, _get_proctime(), mode, buf_paddr, count, lba ); 95 124 #endif 96 125 97 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ; 98 unsigned int error = 0; 99 100 // get the lock protecting IOC 101 _get_lock(&_ioc_lock); 102 103 // set the _ioc_status polling variable 104 _ioc_status = BLOCK_DEVICE_BUSY; 105 106 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buf_paddr; 107 ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32); 108 ioc_address[BLOCK_DEVICE_COUNT] = count; 109 ioc_address[BLOCK_DEVICE_LBA] = lba; 110 111 // There are two policies for transfer completion 112 // detection, depending on the mode argument: 113 114 if ( (mode == IOC_BOOT_PA_MODE) || // We poll directly the IOC_STATUS register 115 (mode == IOC_BOOT_VA_MODE) ) // as IRQs are masked. 126 unsigned int error = 0; 127 128 // get the lock protecting BDV 129 _get_lock(&_bdv_lock); 130 131 // set device registers 132 _bdv_set_register( BLOCK_DEVICE_BUFFER , (unsigned int)buf_paddr ); 133 _bdv_set_register( BLOCK_DEVICE_BUFFER_EXT, (unsigned int)(buf_paddr>>32) ); 134 _bdv_set_register( BLOCK_DEVICE_COUNT , count ); 135 _bdv_set_register( BLOCK_DEVICE_LBA , lba ); 136 137 // In BOOT mode, we launch transfer, and poll the BDV_STATUS 138 // register because IRQs are masked. 139 if ( mode == IOC_BOOT_MODE ) 116 140 { 117 141 // Launch transfert 118 if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;119 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;142 if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE ); 143 else _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ ); 120 144 121 145 unsigned int status; 122 146 do 123 147 { 124 if ( _bdv_get_status( 0, &status ) ) return 1; 125 126 #if GIET_DEBUG_IOC_DRIVER 127 _tty_get_lock( 0 ); 128 _puts("\n[IOC DEBUG] _bdv_access() : ... waiting on IOC_STATUS register ...\n"); 129 _tty_release_lock( 0 ); 148 status = _bdv_get_register( BLOCK_DEVICE_STATUS ); 149 150 #if GIET_DEBUG_BDV_DRIVER 151 _printf("\n[BDV DEBUG] _bdv_access() : ... waiting on BDV_STATUS register ...\n"); 130 152 #endif 131 153 } … … 133 155 (status != BLOCK_DEVICE_READ_ERROR) && 134 156 (status != BLOCK_DEVICE_WRITE_SUCCESS) && 135 (status != BLOCK_DEVICE_WRITE_ERROR) ); 157 (status != BLOCK_DEVICE_WRITE_ERROR) ); // busy waiting 136 158 137 159 // analyse status … … 140 162 141 163 // release lock 142 _release_lock(&_ ioc_lock);164 _release_lock(&_bdv_lock); 143 165 } 144 else // in USER or KERNEL mode, we deschedule the task. 145 // When the task is rescheduled by the ISR, we reset 146 // the _ioc_status variable, and release the lock 166 // in USER or KERNEL mode, we deschedule the task. 167 // When the task is rescheduled, we check the _bdv_status variable, 168 // and release the lock. 169 // We need a critical section, because we must reset the RUN bit 170 // before to launch the transfer, and we don't want to be descheduled 171 // between these two operations. 172 else 147 173 { 148 // We need a critical section, because we must reset the RUN bit 149 // before to launch the transfer, and we want to avoid to be descheduled 150 // between these two operations. 151 152 // Enter critical section 153 _it_disable(); 174 unsigned int save_sr; 175 unsigned int ltid = _get_current_task_id(); 176 unsigned int gpid = _get_procid(); 177 178 // activates BDV interrupts 179 _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 1 ); 180 181 // set the _bdv_status variable 182 _bdv_status = BLOCK_DEVICE_BUSY; 183 184 // enters critical section 185 _it_disable( &save_sr ); 154 186 155 // set _ioc_gtid and reset runnable 156 unsigned int ltid = _get_proc_task_id(); 157 unsigned int pid = _get_procid(); 158 _ioc_gtid = (pid<<16) + ltid; 159 _set_task_slot( pid, ltid, CTX_RUN_ID, 0 ); 187 // set _bdv_gtid and reset runnable 188 _bdv_gtid = (gpid<<16) + ltid; 189 _set_task_slot( gpid, ltid, CTX_RUN_ID, 0 ); 160 190 161 // Launch transfert162 if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;163 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;191 // launch transfer 192 if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE ); 193 else _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ ); 164 194 165 195 // deschedule task 166 196 _ctx_switch(); 167 197 198 // restore SR 199 _it_restore( &save_sr ); 200 168 201 // analyse status 169 error = ( (_ ioc_status == BLOCK_DEVICE_READ_ERROR) ||170 (_ ioc_status == BLOCK_DEVICE_WRITE_ERROR) );171 172 // reset _ ioc_status and release lock173 _ ioc_status = BLOCK_DEVICE_IDLE;174 _release_lock(&_ ioc_lock);202 error = ( (_bdv_status == BLOCK_DEVICE_READ_ERROR) || 203 (_bdv_status == BLOCK_DEVICE_WRITE_ERROR) ); 204 205 // reset _bdv_status and release lock 206 _bdv_status = BLOCK_DEVICE_IDLE; 207 _release_lock(&_bdv_lock); 175 208 } 176 209 177 #if GIET_DEBUG_IOC_DRIVER 178 _tty_get_lock( 0 ); 179 _puts("\n[IOC DEBUG] _bdv_access completed at cycle "); 180 _putd( _get_proctime() ); 181 _puts(" for processor "); 182 _putd( _get_procid() ); 183 _puts(" : error = "); 184 _putd( (unsigned int)error ); 185 _puts("\n"); 186 _tty_release_lock( 0 ); 210 #if GIET_DEBUG_BDV_DRIVER 211 _printf("\n[BDV DEBUG] Processor[%d,%d,%d] exit _bdv_access() at cycle %d\n", 212 x, y, lpid, _get_proctime() ); 187 213 #endif 188 214 … … 191 217 192 218 /////////////////////////////////////////////////////////////////////////////// 193 // _bdv_init() 194 // This function cheks block size, and activates the IOC interrupts. 219 // This function cheks block size, and desactivates the interrupts. 195 220 // Return 0 for success, > 0 if error 196 221 /////////////////////////////////////////////////////////////////////////////// 197 unsigned int _bdv_init( unsigned int channel ) 198 { 199 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ; 200 201 if ( ioc_address[BLOCK_DEVICE_BLOCK_SIZE] != 512 ) 222 unsigned int _bdv_init() 223 { 224 if ( _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE ) != 512 ) 202 225 { 203 _tty_get_lock( 0 ); 204 _puts("\n[GIET ERROR] in _bdv_init() : block size must be 512 bytes\n"); 205 _tty_release_lock( 0 ); 226 _printf("\n[GIET ERROR] in _bdv_init() : block size must be 512 bytes\n"); 206 227 return 1; 207 228 } 208 229 209 if ( channel != 0 ) 210 { 211 _tty_get_lock( 0 ); 212 _puts("\n[GIET ERROR] in _bdv_init() : illegal channel\n"); 213 _tty_release_lock( 0 ); 214 215 return 1; 216 } 217 218 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 230 _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 0 ); 219 231 return 0; 220 232 } 221 233 222 234 /////////////////////////////////////////////////////////////////////////////// 223 // _bdv_read()224 235 // Transfer data from the block device to a memory buffer. 225 236 // - mode : BOOT / KERNEL / USER … … 229 240 // Returns 0 if success, > 0 if error. 230 241 /////////////////////////////////////////////////////////////////////////////// 231 unsigned int _bdv_read( unsigned int mode,232 unsigned int lba,233 paddr_tbuffer,234 unsigned int count)242 unsigned int _bdv_read( unsigned int mode, 243 unsigned int lba, 244 unsigned long long buffer, 245 unsigned int count) 235 246 { 236 247 return _bdv_access( 1, // read access … … 242 253 243 254 /////////////////////////////////////////////////////////////////////////////// 244 // _bdv_write()245 255 // Transfer data from a memory buffer to the block device. 246 256 // - mode : BOOT / KERNEL / USER … … 250 260 // Returns 0 if success, > 0 if error. 251 261 /////////////////////////////////////////////////////////////////////////////// 252 unsigned int _bdv_write( unsigned int mode,253 unsigned int lba,254 paddr_tbuffer,255 unsigned int count )262 unsigned int _bdv_write( unsigned int mode, 263 unsigned int lba, 264 unsigned long long buffer, 265 unsigned int count ) 256 266 { 257 267 return _bdv_access( 0, // write access … … 263 273 264 274 /////////////////////////////////////////////////////////////////////////////// 265 // _bdv_get_status() 266 // This function returns in the status variable, the transfert status, and 267 // acknowledge the IRQ if the IOC controler is not busy. 268 // Returns 0 if success, > 0 if error 269 /////////////////////////////////////////////////////////////////////////////// 270 unsigned int _bdv_get_status( unsigned int channel, 271 unsigned int* status ) 272 { 273 if ( channel != 0 ) 274 { 275 _tty_get_lock( 0 ); 276 _puts("\n[GIET ERROR] in _bdv_get_status() : illegal channel\n"); 277 _tty_release_lock( 0 ); 278 279 return 1; 280 } 281 282 // get IOC base address 283 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base; 284 *status = ioc_address[BLOCK_DEVICE_STATUS]; 285 286 return 0; 287 } 288 289 /////////////////////////////////////////////////////////////////////////////// 290 // _bdv_get_block_size() 291 // This function returns the block_size with which the IOC has been configured. 292 /////////////////////////////////////////////////////////////////////////////// 293 unsigned int _bdv_get_block_size() 294 { 295 // get IOC base address 296 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base; 297 298 return ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 275 // Returns device status. 276 /////////////////////////////////////////////////////////////////////////////// 277 unsigned int _bdv_get_status() 278 { 279 return _bdv_get_register( BLOCK_DEVICE_STATUS ); 280 } 281 282 /////////////////////////////////////////////////////////////////////////////// 283 // Returns block size. 284 /////////////////////////////////////////////////////////////////////////////// 285 unsigned int _bdv_get_block_size() 286 { 287 return _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE ); 288 } 289 290 /////////////////////////////////////////////////////////////////////////////////// 291 // This ISR save the status, acknowledge the IRQ, 292 // and activates the task waiting on IO transfer. 293 // It can be an HWI or a SWI. 294 // 295 // TODO the _set_task_slot access should be replaced by an atomic LL/SC 296 // when the CTX_RUN bool will be replaced by a bit_vector. 297 /////////////////////////////////////////////////////////////////////////////////// 298 void _bdv_isr( unsigned int irq_type, // HWI / WTI 299 unsigned int irq_id, // index returned by ICU 300 unsigned int channel ) // unused 301 { 302 unsigned int procid = _get_procid(); 303 unsigned int cluster_xy = procid / NB_PROCS_MAX; 304 unsigned int lpid = procid % NB_PROCS_MAX; 305 306 // acknowledge WTI in local XCU if required 307 unsigned int value; 308 if ( irq_type == IRQ_TYPE_WTI ) _xcu_get_wti_value( cluster_xy, irq_id, &value ); 309 310 // save status in _bdv_status variable and reset IRQ 311 _bdv_status = _bdv_get_register( BLOCK_DEVICE_STATUS ); 312 313 // identify task waiting on BDV 314 unsigned int rprocid = _bdv_gtid>>16; 315 unsigned int ltid = _bdv_gtid & 0xFFFF; 316 unsigned int remote_xy = rprocid / NB_PROCS_MAX; 317 318 #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlock 319 unsigned int x = cluster_xy >> Y_WIDTH; 320 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 321 unsigned int rx = remote_xy >> Y_WIDTH; 322 unsigned int ry = remote_xy & ((1<<Y_WIDTH)-1); 323 unsigned int rlpid = rprocid % NB_PROCS_MAX; 324 _puts("\n[IRQS DEBUG] Processor["); 325 _putd(x ); 326 _puts(","); 327 _putd(y ); 328 _puts(","); 329 _putd(lpid ); 330 _puts("] enters _bdv_isr() at cycle "); 331 _putd(_get_proctime() ); 332 _puts("\n for task "); 333 _putd(ltid ); 334 _puts(" running on processor["); 335 _putd(rx ); 336 _puts(","); 337 _putd(ry ); 338 _puts(","); 339 _putd(rlpid ); 340 _puts(" / bdv status = "); 341 _putx(_bdv_status ); 342 _puts("\n"); 343 #endif 344 345 // re-activates sleeping task 346 _set_task_slot( rprocid, // global processor index 347 ltid, // local task index on processor 348 CTX_RUN_ID, // CTX_RUN slot 349 1 ); // running 350 351 // requires a context switch for remote processor running the waiting task 352 _xcu_send_wti( remote_xy, // cluster index 353 lpid, // local processor index 354 0 ); // don't force context switch if not idle 299 355 } 300 356 -
soft/giet_vm/giet_drivers/bdv_driver.h
r289 r295 7 7 /////////////////////////////////////////////////////////////////////////////////// 8 8 9 #ifndef _GIET_BDV_DRIVERS_H_ 10 #define _GIET_BDV_DRIVERS_H_ 11 12 #include <mapping_info.h> 9 #ifndef _GIET_BDV_DRIVER_H_ 10 #define _GIET_BDV_DRIVER_H_ 13 11 14 12 /////////////////////////////////////////////////////////////////////////////////// 15 // BDV access functions and variables (vci_block_device)13 // BDV global variables 16 14 /////////////////////////////////////////////////////////////////////////////////// 17 15 18 extern unsigned int _bdv_init( unsigned int channel ); 16 extern unsigned int _bdv_lock; // BDV is a shared ressource 17 extern volatile unsigned int _bdv_status; // required for IRQ signaling 18 extern volatile unsigned int _bdv_gtid; // descheduled task id = gpid<<16 + ltid 19 19 20 extern unsigned int _bdv_write( unsigned int mode, 21 unsigned int lba, 22 paddr_t buffer, 23 unsigned int count ); 20 /////////////////////////////////////////////////////////////////////////////////// 21 // BDV registers, operations and status values 22 /////////////////////////////////////////////////////////////////////////////////// 24 23 25 extern unsigned int _bdv_read( unsigned int mode, 26 unsigned int lba, 27 paddr_t buffer, 28 unsigned int count ); 24 enum BDV_registers 25 { 26 BLOCK_DEVICE_BUFFER, 27 BLOCK_DEVICE_LBA, 28 BLOCK_DEVICE_COUNT, 29 BLOCK_DEVICE_OP, 30 BLOCK_DEVICE_STATUS, 31 BLOCK_DEVICE_IRQ_ENABLE, 32 BLOCK_DEVICE_SIZE, 33 BLOCK_DEVICE_BLOCK_SIZE, 34 BLOCK_DEVICE_BUFFER_EXT, 35 }; 29 36 30 extern unsigned int _bdv_get_status( unsigned int channel, 31 unsigned int* status ); 37 enum BDV_operations 38 { 39 BLOCK_DEVICE_NOOP, 40 BLOCK_DEVICE_READ, 41 BLOCK_DEVICE_WRITE, 42 }; 43 44 enum BDV_status 45 { 46 BLOCK_DEVICE_IDLE, 47 BLOCK_DEVICE_BUSY, 48 BLOCK_DEVICE_READ_SUCCESS, 49 BLOCK_DEVICE_WRITE_SUCCESS, 50 BLOCK_DEVICE_READ_ERROR, 51 BLOCK_DEVICE_WRITE_ERROR, 52 BLOCK_DEVICE_ERROR, 53 }; 54 55 /////////////////////////////////////////////////////////////////////////////////// 56 // BDV access functions (vci_block_device) 57 /////////////////////////////////////////////////////////////////////////////////// 58 59 extern unsigned int _bdv_init(); 60 61 extern unsigned int _bdv_write( unsigned int mode, 62 unsigned int lba, 63 unsigned long long buffer, 64 unsigned int count ); 65 66 extern unsigned int _bdv_read( unsigned int mode, 67 unsigned int lba, 68 unsigned long long buffer, 69 unsigned int count ); 70 71 extern unsigned int _bdv_get_status(); 32 72 33 73 extern unsigned int _bdv_get_block_size(); 74 75 extern void _bdv_isr( unsigned irq_type, 76 unsigned irq_id, 77 unsigned channel ); 34 78 35 79 /////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/cma_driver.h
r258 r295 29 29 }; 30 30 31 /////////////////////////////////////////////////////////////////////////////////// 32 // CMA (vci_chbuf_dma) low-level access functions 33 /////////////////////////////////////////////////////////////////////////////////// 34 35 extern unsigned int _cma_get_register( unsigned int channel, 36 unsigned int index ); 37 38 extern void _cma_set_register( unsigned int channel, 39 unsigned int index, 40 unsigned int value ); 41 42 extern void _cma_isr( unsigned int irq_type, 43 unsigned int irq_id, 44 unsigned int channel ); 45 46 /////////////////////////////////////////////////////////////////////////////////// 47 31 48 #endif 32 49 -
soft/giet_vm/giet_drivers/dma_driver.c
r267 r295 196 196 unsigned int procid = _get_procid(); 197 197 unsigned int cluster_xy = procid/NB_PROCS_MAX; 198 unsigned int x = cluster_xy >> Y_WIDTH; 199 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 198 200 unsigned int channel_id = procid%NB_PROCS_MAX; 199 201 … … 203 205 204 206 #if GIET_DEBUG_DMA_DRIVER 205 _tty_get_lock( 0 ); 206 _puts("\n[DMA DEBUG] Enter _dma_copy() at cycle "); 207 _putd( _get_proctime() ); 208 _puts("\n - vspace_id = "); 209 _putx( vspace_id ); 210 _puts("\n - cluster_xy = "); 211 _putx( cluster_xy ); 212 _puts("\n - channel_id = "); 213 _putx( channel_id ); 214 _puts("\n - dest = "); 215 _putx( (unsigned int)dest ); 216 _puts("\n - source = "); 217 _putx( (unsigned int)source ); 218 _puts("\n - bytes = "); 219 _putd( size ); 220 _tty_release_lock( 0 ); 207 unsigned int x = cluster_xy >> Y_WIDTH; 208 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 209 210 _printf("\n[DMA DEBUG] Processor[%d,%d,%d] enters _dma_copy() at cycle %d\n" 211 " - vspace_id = %d\n" 212 " - cluster_xy = %x\n" 213 " - channel_id = %d\n" 214 " - dest = %x\n" 215 " - source = %x\n" 216 " - bytes = %x\n", 217 x, y, channel_id, _get_proctime(), vspace_id, cluster_xy, 218 (unsigned int)dest, (unsigned int)source, size ); 221 219 #endif 222 220 … … 226 224 (size & 0x3) ) 227 225 { 228 _tty_get_lock( 0 ); 229 _puts("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n"); 230 _tty_release_lock( 0 ); 226 _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n"); 231 227 _exit(); 232 228 } … … 242 238 if ( ko ) 243 239 { 244 _tty_get_lock( 0 ); 245 _puts("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n"); 246 _tty_release_lock( 0 ); 240 _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n"); 247 241 _exit(); 248 242 } … … 257 251 if ( ko ) 258 252 { 259 _tty_get_lock( 0 ); 260 _puts("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n"); 261 _tty_release_lock( 0 ); 253 _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n"); 262 254 _exit(); 263 255 } … … 266 258 267 259 #if GIET_DEBUG_DMA_DRIVER 268 _tty_get_lock( 0 ); 269 _puts("\n - src_paddr = "); 270 _putl( src_paddr ); 271 _puts("\n - dst_paddr = "); 272 _putl( dst_paddr ); 273 _puts("\n"); 274 _tty_release_lock( 0 ); 260 _printf(" - src_paddr = %llx\n" 261 " - dst_paddr = %llx\n", 262 src_paddr, dst_paddr ); 275 263 #endif 276 264 … … 282 270 if ( ko ) 283 271 { 284 _tty_get_lock( 0 ); 285 _puts("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n"); 286 _tty_release_lock( 0 ); 272 _printf("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n"); 287 273 _exit(); 288 274 } … … 297 283 298 284 #if GIET_DEBUG_DMA_DRIVER 299 _tty_get_lock( 0 ); 300 _puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n"); 301 _tty_release_lock( 0 ); 285 _printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n"); 302 286 #endif 303 287 … … 307 291 if( status != DMA_SUCCESS ) 308 292 { 309 _tty_get_lock( 0 ); 310 _puts("\n[GIET ERROR] in _dma_copy() : DMA_STATUS error = "); 311 _putd( status ); 312 _puts("\n"); 313 _tty_release_lock( 0 ); 293 _printf("\n[GIET ERROR] in _dma_copy() : DMA_STATUS = %x\n", status ); 314 294 _exit(); 315 295 } … … 318 298 319 299 #if GIET_DEBUG_DMA_DRIVER 320 _tty_get_lock( 0 ); 321 _puts("\n[DMA DEBUG] _dma_copy() completed at cycle "); 322 _putd( _get_proctime() ); 323 _puts("\n"); 324 _tty_release_lock( 0 ); 300 _printf("\n[DMA DEBUG] _dma_copy() completed at cycle %d\n", _get_proctime() ); 325 301 #endif 326 302 327 303 #else // NB_DMA_CHANNELS == 0 328 _tty_get_lock( 0 ); 329 _puts("\n[GIET ERROR] in _dma_copy() : NB_DMA_CHANNELS = 0 !\n"); 330 _tty_release_lock( 0 ); 304 _printf("\n[GIET ERROR] in _dma_copy() : NB_DMA_CHANNELS = 0 !\n"); 331 305 _exit(); 332 306 #endif -
soft/giet_vm/giet_drivers/fbf_driver.c
r275 r295 7 7 // The fbf_driver.c and fbf_driver.h files are part ot the GIET-VM kernel. 8 8 // This driver supports the SoCLib vci_framebuffer component. 9 //10 // It can exist only one frame buffer in the architecture.11 9 // 12 10 // There exist two methods to access the VciFrameBuffer device: … … 59 57 unsigned int length) 60 58 { 61 char* fb_address = (char *)&seg_fbf_base + offset; 62 _memcpy( fb_address, buffer, length); 59 char* fbf_address = (char *)&seg_fbf_base + offset; 60 61 _memcpy( fbf_address, buffer, length); 62 63 63 return 0; 64 64 } … … 74 74 unsigned int length) 75 75 { 76 char* fb_address = (char *)&seg_fbf_base + offset; 77 _memcpy( buffer, fb_address, length); 76 char* fbf_address = (char *)&seg_fbf_base + offset; 77 78 _memcpy( buffer, fbf_address, length); 79 78 80 return 0; 79 81 } … … 145 147 if ( channel_id >= NB_CMA_CHANNELS ) 146 148 { 147 _tty_get_lock( 0 ); 148 _puts("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n"); 149 _tty_release_lock( 0 ); 149 _printf("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n"); 150 150 return 1; 151 151 } … … 154 154 if ( sizeof(fb_cma_channel_t) != 32 ) 155 155 { 156 _tty_get_lock( 0 ); 157 _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n"); 158 _tty_release_lock( 0 ); 156 _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n"); 159 157 return 1; 160 158 } … … 163 161 if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F ) 164 162 { 165 _tty_get_lock( 0 ); 166 _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n"); 167 _tty_release_lock( 0 ); 163 _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n"); 168 164 return 1; 169 165 } … … 172 168 if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 173 169 { 174 _tty_get_lock( 0 ); 175 _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n"); 176 _tty_release_lock( 0 ); 170 _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n"); 177 171 return 1; 178 172 } … … 189 183 if (ko) 190 184 { 191 _tty_get_lock( 0 ); 192 _puts("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n"); 193 _tty_release_lock( 0 ); 185 _printf("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n"); 194 186 return 1; 195 187 } … … 204 196 if (ko) 205 197 { 206 _tty_get_lock( 0 ); 207 _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n"); 208 _tty_release_lock( 0 ); 198 _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n"); 209 199 return 1; 210 200 } 211 201 if ((flags & PTE_U) == 0) 212 202 { 213 _tty_get_lock( 0 ); 214 _puts("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n"); 215 _tty_release_lock( 0 ); 203 _printf("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n"); 216 204 return 1; 217 205 } … … 226 214 if (ko) 227 215 { 228 _tty_get_lock( 0 ); 229 _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n"); 230 _tty_release_lock( 0 ); 216 _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n"); 231 217 return 1; 232 218 } 233 219 if ((flags & PTE_U) == 0) 234 220 { 235 _tty_get_lock( 0 ); 236 _puts("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n"); 237 _tty_release_lock( 0 ); 221 _printf("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n"); 238 222 return 1; 239 223 } … … 251 235 if (ko) 252 236 { 253 _tty_get_lock( 0 ); 254 _puts("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n"); 255 _tty_release_lock( 0 ); 237 _printf("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n"); 256 238 return 1; 257 239 } … … 262 244 263 245 #if GIET_DEBUG_FBF_DRIVER 264 _tty_get_lock( 0 ); 265 _puts("\n[CMA DEBUG] fb_cma_init()"); 266 _puts("\n - fbf pbase = "); 267 _putl( _fb_cma_channel[channel_id].fbf ); 268 _puts("\n - buf0 pbase = "); 269 _putl( _fb_cma_channel[channel_id].buf0 ); 270 _puts("\n - buf1 pbase = "); 271 _putl( _fb_cma_channel[channel_id].buf1 ); 272 _puts("\n - channel pbase = "); 273 _putl( _fb_cma_desc_paddr[channel_id] ); 274 _puts("\n"); 275 _tty_release_lock( 0 ); 246 _printf("\n[CMA DEBUG] enters _fb_cma_init()\n" 247 " - fbf pbase = %l\n" 248 " - buf0 pbase = %l\n" 249 " - buf1 pbase = %l\n" 250 " - channel pbase = %l\n" 251 _fb_cma_channel[channel_id].fbf, 252 _fb_cma_channel[channel_id].buf0, 253 _fb_cma_channel[channel_id].buf1, 254 _fb_cma_desc_paddr[channel_id] ); 276 255 #endif 277 256 … … 283 262 284 263 // CMA channel activation 285 unsigned int* cma_vbase = (unsigned int *)&seg_cma_base; 286 unsigned int offset = channel_id * CHBUF_CHANNEL_SPAN; 287 288 cma_vbase[offset + CHBUF_SRC_DESC] = (unsigned int)(desc_paddr & 0xFFFFFFFF); 289 cma_vbase[offset + CHBUF_SRC_EXT] = (unsigned int)(desc_paddr >> 32); 290 cma_vbase[offset + CHBUF_SRC_NBUFS] = 2; 291 cma_vbase[offset + CHBUF_DST_DESC] = (unsigned int)(desc_paddr & 0xFFFFFFFF) + 16; 292 cma_vbase[offset + CHBUF_DST_EXT] = (unsigned int)(desc_paddr >> 32); 293 cma_vbase[offset + CHBUF_DST_NBUFS] = 1; 294 cma_vbase[offset + CHBUF_BUF_SIZE] = length; 295 cma_vbase[offset + CHBUF_PERIOD] = 300; 296 cma_vbase[offset + CHBUF_RUN] = 1; 297 264 _cma_set_register( channel_id, CHBUF_SRC_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) ); 265 _cma_set_register( channel_id, CHBUF_SRC_EXT , (unsigned int)(desc_paddr >> 32) ); 266 _cma_set_register( channel_id, CHBUF_SRC_NBUFS, 2 ); 267 _cma_set_register( channel_id, CHBUF_DST_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) + 16 ); 268 _cma_set_register( channel_id, CHBUF_DST_EXT , (unsigned int)(desc_paddr >> 32) ); 269 _cma_set_register( channel_id, CHBUF_DST_NBUFS, 1 ); 270 _cma_set_register( channel_id, CHBUF_BUF_SIZE , length ); 271 _cma_set_register( channel_id, CHBUF_PERIOD , 300 ); 272 _cma_set_register( channel_id, CHBUF_RUN , 1 ); 298 273 return 0; 299 274 300 275 #else 301 302 _tty_get_lock( 0 ); 303 _puts("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n"); 304 _tty_release_lock( 0 ); 305 276 _printf("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n"); 306 277 return 1; 307 278 #endif 308 279 } 280 309 281 //////////////////////////////////////////////////////////////////////////////////// 310 282 // _fb_cma_write() … … 330 302 331 303 volatile paddr_t buf_paddr; 332 unsigned int buf_length;333 304 unsigned int full = 1; 334 305 … … 339 310 340 311 #if GIET_DEBUG_FBF_DRIVER 341 _tty_get_lock( 0 ); 342 _puts("\n[CMA DEBUG] fb_cma_write() for CMA channel "); 343 _putd( channel_id ); 344 _puts(" / buf_id = "); 345 _putd( buffer_id ); 346 _puts("\n"); 347 _tty_release_lock( 0 ); 312 _printf("\n[CMA DEBUG] _fb_cma_write() for CMA channel %d / bufid = %d at cycle %d\n", 313 channel_id, buffer_id, _get_proctime() ); 348 314 #endif 349 315 … … 357 323 358 324 // INVAL L1 cache for the channel descriptor, 359 _dcache_buf_invalidate( &_fb_cma_channel[channel_id], 32 );325 _dcache_buf_invalidate( (void*)&_fb_cma_channel[channel_id], 32 ); 360 326 } 361 327 … … 367 333 count++; 368 334 if ( count == 10 ) _exit(); 369 370 #if GIET_DEBUG_FBF_DRIVER371 _tty_get_lock( 0 );372 _puts(" - buffer descriptor = ");373 _putl( buf_paddr );374 _puts(" at cycle ");375 _putd( _get_proctime() );376 _puts("\n");377 _tty_release_lock( 0 );378 #endif379 380 335 } 381 336 … … 408 363 #else 409 364 410 _tty_get_lock( 0 ); 411 _puts("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n"); 412 _tty_release_lock( 0 ); 365 _printf("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n"); 413 366 return 1; 414 367 … … 427 380 unsigned int channel_id = _get_context_slot(CTX_CMA_ID); 428 381 382 #if GIET_DEBUG_FBF_DRIVER 383 _printf("\n[CMA DEBUG] _fb_cma_stop() for CMA channel %d at cycle %d\n", 384 channel_id, _get_proctime() ); 385 #endif 386 429 387 // CMA channel desactivation 430 unsigned int* cma_vbase = (unsigned int *)&seg_cma_base; 431 unsigned int offset = channel_id * CHBUF_CHANNEL_SPAN; 432 cma_vbase[offset + CHBUF_RUN] = 0; 388 _cma_set_register( channel_id, CHBUF_RUN, 0 ); 389 433 390 return 0; 434 391 435 392 #else 436 393 437 _tty_get_lock( 0 ); 438 _puts("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n"); 439 _tty_release_lock( 0 ); 394 _printf("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n"); 440 395 return 1; 441 396 -
soft/giet_vm/giet_drivers/hba_driver.c
r289 r295 2 2 // File : hba_driver.c 3 3 // Date : 23/11/2013 4 // Author : alain greiner and zhang4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// … … 9 9 // block oriented, external storage contrÃŽler, respecting the AHCI standard. 10 10 // 11 // It can exist only one ahci-device controler in the architecture. 11 // The seg_ioc_base (standard HBA virtual base address) and seg_ioc_base_bis 12 // (backup HBA virtual base address) must be defined in giet_vsegs.ld file. 13 ////////////////////////////////////////////////////////////////////////////////// 14 // Implementation notes: 12 15 // 13 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function,14 // that is always blocking, but can be called in 4 modes:16 // 1. In order to share code, the two _hba_read() and _hba_write() functions 17 // call the same _hba_set_cmd() function. 15 18 // 16 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address 17 // as a physical address (as the page tables are not build) and use a polling 18 // policy on the IOC_STATUS register to detect transfer completion, as 19 // hardware interrupts are not activated. This mode is used by the 20 // boot code to load the map.bin file into memory. 21 // 22 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to 23 // compute the buffer physical address, and use a polling policy on IOC_STATUS 24 // register to detect transfer completion. This mode is used by the boot code 25 // to load the various .elf files into memory. 26 // 27 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to 28 // compute the buffer physical address, and use a descheduling strategy: 29 // The ISR executed when transfer completes should restart the calling task. 30 // There is no checking of user access right to the memory buffer. 31 // This mode must be used to access IOC, for an "open" system call. 32 // 33 // - In USER mode, the _ioc_access() function makes a V2P translation to 34 // compute the buffer physical address, and use a descheduling strategy: 35 // The ISR executed when transfer completes should restart the calling task, 36 // The user access right to the memory buffer must be checked. 37 // This mode must be used to access IOC, for a "read/write" system call. 38 // 39 // As the IOC component can be used by several programs running in parallel, 40 // the _ioc_lock variable guaranties exclusive access to the device. The 41 // _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock. 42 // 43 // The IOMMU can be activated or not: 44 // 45 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 46 // the IOC peripheral, in the I/O virtual space, and the user buffer is 47 // dynamically remapped in the IOMMU page table. The corresponding entry 48 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable. 49 // The number of pages to be unmapped is stored in the _ioc_npages variable. 50 // The number of PT2 entries is dynamically computed and stored in the 51 // kernel _ioc_iommu_npages variable. It cannot be larger than 512. 52 // The user buffer is unmapped by the _ioc_completed() function when 53 // the transfer is completed. 54 // 55 // 2/ If the IOMMU is not used, we check that the user buffer is mapped to a 56 // contiguous physical buffer (this is generally true because the user space 57 // page tables are statically constructed to use contiguous physical memory). 58 // 59 // Finally, the memory buffer must fulfill the following conditions: 60 // - The buffer must be word aligned, 61 // - The buffer must be mapped in user space for an user access, 62 // - The buffer must be writable in case of (to_mem) access, 63 // - The total number of physical pages occupied by the user buffer cannot 64 // be larger than 512 pages if the IOMMU is activated, 65 // - All physical pages occupied by the user buffer must be contiguous 66 // if the IOMMU is not activated. 67 // An error code is returned if these conditions are not verified. 68 /////////////////////////////////////////////////////////////////////////////////// 69 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file. 19 // 2. All accesses to HBA registers are done by the two 20 // _hba_set_register() and _hba_get_register() low-level functions, 21 // that are handling virtual / physical extended addressing. 70 22 /////////////////////////////////////////////////////////////////////////////////// 71 23 … … 80 32 #include <vmem.h> 81 33 82 #if !defined( NB_HBA_CHANNELS ) 83 # error: You must define NB_HBA_CHANNELS in the hard_config.h file 84 #endif 85 86 #if ( NB_HBA_CHANNELS > 8 ) 87 # error: NB_HBA_CHANNELS cannot be larger than 8 88 #endif 89 90 #if !defined( USE_IOB ) 91 # error: You must define USE_IOB in the hard_config.h file 92 #endif 93 94 #if !defined(GIET_USE_IOMMU) 95 # error: You must define GIET_USE_IOMMU in the giet_config.h file 34 #if !defined( NB_IOC_CHANNELS ) 35 # error: You must define NB_IOC_CHANNELS in the hard_config.h file 36 #endif 37 38 #if ( NB_IOC_CHANNELS > 8 ) 39 # error: NB_IOC_CHANNELS cannot be larger than 8 96 40 #endif 97 41 … … 103 47 104 48 // command list array (one per channel) 105 hba_cmd_list_t hba_cmd_list[NB_ HBA_CHANNELS] __attribute__((aligned(0x1000)));49 hba_cmd_list_t hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000))); 106 50 107 51 // command tables array (32 command tables per channel) 108 hba_cmd_table_t hba_cmd_table[NB_ HBA_CHANNELS][32] __attribute__((aligned(0x1000)));52 hba_cmd_table_t hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000))); 109 53 110 54 // command list physical addresses array (one per channel) 111 paddr_t hba_cmd_list_paddr[NB_ HBA_CHANNELS];55 paddr_t hba_cmd_list_paddr[NB_IOC_CHANNELS]; 112 56 113 57 // command tables physical addresses array (32 command tables per channel) 114 paddr_t hba_cmd_table_paddr[NB_ HBA_CHANNELS][32];58 paddr_t hba_cmd_table_paddr[NB_IOC_CHANNELS][32]; 115 59 116 60 // command list pointer array (one per channel) 117 unsigned int hba_cmd_slot[NB_HBA_CHANNELS]; 118 119 ////////////////////////////////////////////////////////////////// 120 // This function returns the status of a given channel. 121 // return 0 if success, >0 if error 122 ////////////////////////////////////////////////////////////////// 123 unsigned int _hba_get_status( unsigned int channel, 124 unsigned int* status ) 125 { 126 volatile unsigned int* hba_address; 127 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 128 129 if( channel >= NB_HBA_CHANNELS ) 130 { 131 _tty_get_lock( 0 ); 132 _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 133 _tty_release_lock( 0 ); 134 return 1; 135 } 136 else 137 { 138 *status = hba_address[HBA_PXIS]; 139 return 0; 140 } 141 } 142 ////////////////////////////////////////////////////////////////// 143 // This function reset the status resgister for a given channel. 144 // return 0 if success, >0 if error 145 ////////////////////////////////////////////////////////////////// 146 unsigned int _hba_reset_status( unsigned int channel ) 147 { 148 volatile unsigned int* hba_address; 149 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 150 151 if( channel >= NB_HBA_CHANNELS ) 152 { 153 _tty_get_lock( 0 ); 154 _puts("\n[GIET ERROR] in _hba_reset_status() : illegal channel\n"); 155 _tty_release_lock( 0 ); 156 return 1; 157 } 158 else 159 { 160 hba_address[HBA_PXIS] = 0; 161 return 0; 162 } 163 } 61 unsigned int hba_cmd_slot[NB_IOC_CHANNELS]; 62 63 ////////////////////////////////////////////////////////////////////////////// 64 // This low level function returns the value of register (channel / index) 65 ////////////////////////////////////////////////////////////////////////////// 66 unsigned int _hba_get_register( unsigned int channel, 67 unsigned int index ) 68 { 69 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index; 70 return _io_extended_read( vaddr ); 71 } 72 73 ////////////////////////////////////////////////////////////////////////////// 74 // This low level function set a new value in register (channel / index) 75 ////////////////////////////////////////////////////////////////////////////// 76 void _hba_set_register( unsigned int channel, 77 unsigned int index, 78 unsigned int value ) 79 { 80 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index; 81 _io_extended_write( vaddr, value ); 82 } 83 84 164 85 /////////////////////////////////////////////////////////////////////////////// 165 86 // This function register a command in both the command list … … 171 92 // return 0 if success, > 0 if error 172 93 /////////////////////////////////////////////////////////////////////////////// 173 unsigned int _hba_cmd_set( unsigned int is_read, // to memory 94 unsigned int _hba_cmd_set( unsigned int channel, // channel index 95 unsigned int is_read, // to memory 174 96 unsigned int lba, // logic block address 175 unsigned int buf_vaddr, // buffer virtual address97 paddr_t buffer, // buffer physical address 176 98 unsigned int count ) // number of blocks 177 99 { 178 volatile unsigned int *hba_address;179 180 100 unsigned int block_size; // defined by the block device (bytes) 181 unsigned int channel_id; // channel index182 101 unsigned int pxci; // command list status 183 102 unsigned int cmd_id; // command index in command list 184 unsigned int buf_id; // for physical buffers covering user buffer 185 unsigned int user_pt_vbase; // user page table virtual base address 186 unsigned int vpn; // for all pages covering the userbuffer 187 unsigned int vpn_min; // first virtual page index for user buffer 188 unsigned int vpn_max; // last virtual page index for user buffer 189 unsigned int offset; // unaligned bytes in page frame: buf_vaddr & 0xFFF 190 unsigned int offset_last; // unaligned bytes in last frame 103 191 104 hba_cmd_desc_t* cmd_desc; // command descriptor pointer 192 105 hba_cmd_table_t* cmd_table; // command table pointer … … 195 108 196 109 // check buffer alignment 197 if( buf_vaddr & (block_size-1) ) 198 { 199 _tty_get_lock( 0 ); 200 _puts("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n"); 201 _tty_release_lock( 0 ); 110 if( buffer & (block_size-1) ) 111 { 112 _printf("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n"); 202 113 return 1; 203 114 } 204 115 205 // get channel index 206 channel_id = _get_context_slot(CTX_HBA_ID); 207 if ( channel_id == 0xFFFFFFFF ) 208 { 209 _tty_get_lock( 0 ); 210 _puts("\n[GIET ERROR] in _hba_set_cmd() : no HBA channel allocated\n"); 211 _tty_release_lock( 0 ); 116 // get command list status from PXCI register 117 pxci = _hba_get_register( channel, HBA_PXCI ); 118 119 // get command index and return error if command list full 120 cmd_id = hba_cmd_slot[channel]; 121 if( pxci & (1<<cmd_id ) ) 122 { 123 _printf("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel %d\n", 124 channel ); 212 125 return 1; 213 126 } 214 127 215 // get hba device address216 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN * channel_id);217 218 // get command list status219 pxci = hba_address[HBA_PXCI];220 221 // get command index and return error if command list full222 cmd_id = hba_cmd_slot[channel_id];223 if( pxci & (1<<cmd_id ) )224 {225 _tty_get_lock( 0 );226 _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full in channel \n");227 _putd( channel_id );228 _puts("\n");229 _tty_release_lock( 0 );230 return 1;231 }232 233 128 // compute pointers on command descriptor and command table 234 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel_id].desc[cmd_id])); 235 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel_id][cmd_id])); 129 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id])); 130 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id])); 131 132 // set buffer descriptor in command table 133 cmd_table->entry[0].dba = (unsigned int)(buffer); 134 cmd_table->entry[0].dbau = (unsigned int)(buffer >> 32); 135 cmd_table->entry[0].dbc = count * block_size; 136 137 // initialize command table header 138 cmd_table->header.lba0 = (char)lba; 139 cmd_table->header.lba1 = (char)(lba>>8); 140 cmd_table->header.lba2 = (char)(lba>>16); 141 cmd_table->header.lba3 = (char)(lba>>24); 142 cmd_table->header.lba4 = 0; 143 cmd_table->header.lba5 = 0; 144 145 // initialise command descriptor 146 cmd_desc->prdtl[0] = 1; 147 cmd_desc->prdtl[1] = 0; 148 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]); 149 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32); 150 if( is_read ) cmd_desc->flag[0] = 0x00; 151 else cmd_desc->flag[0] = 0x40; 152 153 // update PXCI register 154 _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) ); 155 156 // update command pointer 157 hba_cmd_slot[channel] = (cmd_id + 1)%32; 158 159 return 0; 160 } 161 162 /* This can be used for a future use with buffer in virtual space 236 163 237 164 // get user space page table virtual address … … 262 189 if ( ko ) 263 190 { 264 _tty_get_lock( 0 ); 265 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n"); 266 _tty_release_lock( 0 ); 191 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n"); 267 192 return 1; 268 193 } 269 194 if ((flags & PTE_U) == 0) 270 195 { 271 _tty_get_lock( 0 ); 272 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 273 _tty_release_lock( 0 ); 196 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 274 197 return 1; 275 198 } 276 199 if (((flags & PTE_W) == 0 ) && (is_read == 0) ) 277 200 { 278 _tty_get_lock( 0 ); 279 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 280 _tty_release_lock( 0 ); 201 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 281 202 return 1; 282 203 } … … 285 206 if( buf_id > 245 ) 286 207 { 287 _tty_get_lock( 0 ); 288 _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 289 _tty_release_lock( 0 ); 208 _printf("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 290 209 return 1; 291 210 } … … 301 220 302 221 #if GIET_DEBUG_HBA_DRIVER 303 _p uts("\n- buf_index = ");222 _printf("\n- buf_index = "); 304 223 _putd( buf_id ); 305 _p uts(" / paddr = ");224 _printf(" / paddr = "); 306 225 _putl( paddr ); 307 _p uts(" / count = ");226 _printf(" / count = "); 308 227 _putd( count ); 309 _p uts("\n");228 _printf("\n"); 310 229 #endif 311 230 buf_id++; … … 320 239 321 240 #if GIET_DEBUG_HBA_DRIVER 322 _p uts("\n- buf_index = ");241 _printf("\n- buf_index = "); 323 242 _putd( buf_id ); 324 _p uts(" / paddr = ");243 _printf(" / paddr = "); 325 244 _putl( paddr ); 326 _p uts(" / count = ");245 _printf(" / count = "); 327 246 _putd( count ); 328 _p uts("\n");247 _printf("\n"); 329 248 #endif 330 249 buf_id++; … … 340 259 341 260 #if GIET_DEBUG_HBA_DRIVER 342 _p uts("\n- buf_index = ");261 _printf("\n- buf_index = "); 343 262 _putd( buf_id ); 344 _p uts(" / paddr = ");263 _printf(" / paddr = "); 345 264 _putl( paddr ); 346 _p uts(" / count = ");265 _printf(" / count = "); 347 266 _putd( count ); 348 _p uts("\n");267 _printf("\n"); 349 268 #endif 350 269 buf_id++; … … 357 276 358 277 #if GIET_DEBUG_HBA_DRIVER 359 _p uts("\n- buf_index = ");278 _printf("\n- buf_index = "); 360 279 _putd( buf_id ); 361 _p uts(" / paddr = ");280 _printf(" / paddr = "); 362 281 _putl( paddr ); 363 _p uts(" / count = ");282 _printf(" / count = "); 364 283 _putd( count ); 365 _p uts("\n");284 _printf("\n"); 366 285 #endif 367 286 buf_id++; … … 376 295 377 296 #if GIET_DEBUG_HBA_DRIVER 378 _p uts("\n- buf_index = ");297 _printf("\n- buf_index = "); 379 298 _putd( buf_id ); 380 _p uts(" / paddr = ");299 _printf(" / paddr = "); 381 300 _putl( paddr ); 382 _p uts(" / count = ");301 _printf(" / count = "); 383 302 _putd( count ); 384 _p uts("\n");303 _printf("\n"); 385 304 #endif 386 305 buf_id++; 387 306 } 388 307 } 389 390 // initialize command table header 391 cmd_table->header.lba0 = (char)lba; 392 cmd_table->header.lba1 = (char)(lba>>8); 393 cmd_table->header.lba2 = (char)(lba>>16); 394 cmd_table->header.lba3 = (char)(lba>>24); 395 396 // initialise command descriptor 397 cmd_desc->prdtl[0] = (unsigned char)(buf_id); 398 cmd_desc->prdtl[1] = (unsigned char)(buf_id>>8); 399 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]); 400 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]>>32); 401 if( is_read ) cmd_desc->flag[0] = 0x00; 402 else cmd_desc->flag[0] = 0x40; 403 404 // update PXCI register 405 hba_address[HBA_PXCI] = (1<<cmd_id); 406 407 // update command pointer 408 hba_cmd_slot[channel_id] = (cmd_id + 1)%32; 409 410 return 0; 411 } 308 */ 309 310 412 311 /////////////////////////////////////////////////////////////////// 413 312 // Register a write command in Command List and Command Table 414 // for a single buffer.313 // for a single physical buffer. 415 314 // Returns 0 if success, > 0 if error. 416 315 /////////////////////////////////////////////////////////////////// 417 unsigned int _hba_write( unsigned int mode, 316 unsigned int _hba_write( unsigned int channel, 317 unsigned int mode, 418 318 unsigned int lba, 419 void*buffer,319 paddr_t buffer, 420 320 unsigned int count ) 421 321 { 422 return _hba_cmd_set( 0, lba, (unsigned int)buffer, count ); 322 return _hba_cmd_set( channel, 323 0, // write 324 lba, 325 buffer, 326 count ); 423 327 } 424 328 425 329 /////////////////////////////////////////////////////////////////// 426 330 // Register a read command in Command List and Command Table 427 // for a single buffer.331 // for a single physical buffer. 428 332 // Returns 0 if success, > 0 if error. 429 333 /////////////////////////////////////////////////////////////////// 430 unsigned int _hba_read( unsigned int mode, 334 unsigned int _hba_read( unsigned int channel, 335 unsigned int mode, 431 336 unsigned int lba, 432 void*buffer,337 paddr_t buffer, 433 338 unsigned int count ) 434 339 { 435 return _hba_cmd_set( 1, lba, (unsigned int)buffer, count ); 436 } 340 return _hba_cmd_set( channel, 341 1, // read 342 lba, 343 buffer, 344 count ); 345 } 346 437 347 ////////////////////////////////////////////////////////////////// 438 348 // This function initializes for a given channel … … 453 363 unsigned int pt = _get_context_slot(CTX_PTAB_ID); 454 364 455 // HBA registers 456 unsigned int* hba_address; 457 hba_address = (unsigned int*)&seg_ioc_base + HBA_SPAN * channel; 458 459 hba_address[HBA_PXCLB] = (unsigned int)(&hba_cmd_list[channel]); 460 hba_address[HBA_PXCLBU] = 0; 461 hba_address[HBA_PXIE] = 0x40000001; 462 hba_address[HBA_PXIS] = 0; 463 hba_address[HBA_PXCI] = 0; 464 hba_address[HBA_PXCMD] = 1; 365 // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG) 366 _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] ); 367 _hba_set_register( channel, HBA_PXCLBU, 0 ); 368 _hba_set_register( channel, HBA_PXIE , 0x40000001 ); 369 _hba_set_register( channel, HBA_PXIS , 0 ); 370 _hba_set_register( channel, HBA_PXCI , 0 ); 371 _hba_set_register( channel, HBA_PXCMD , 1 ); 465 372 466 373 // command list pointer … … 475 382 if ( fail ) 476 383 { 477 _tty_get_lock( 0 ); 478 _puts("[GIET ERROR] in _hba_init() : command list unmapped\n"); 479 _tty_release_lock( 0 ); 384 _printf("[GIET ERROR] in _hba_init() : command list unmapped\n"); 480 385 return 1; 481 386 } … … 492 397 if ( fail ) 493 398 { 494 _tty_get_lock( 0 ); 495 _puts("[GIET ERROR] in _hba_init() : command table unmapped\n"); 496 _tty_release_lock( 0 ); 399 _printf("[GIET ERROR] in _hba_init() : command table unmapped\n"); 497 400 return 1; 498 401 } … … 513 416 } 514 417 418 ///////////////////////////////////////////////////////////////////////////////////// 419 // This function returns the content of the HBA_PXIS register for a given channel, 420 // and reset this register to acknoledge IRQ. 421 // return 0 if success, > 0 if error 422 ///////////////////////////////////////////////////////////////////////////////////// 423 unsigned int _hba_get_status( unsigned int channel ) 424 { 425 426 if( channel >= NB_IOC_CHANNELS ) 427 { 428 _printf("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 429 _exit(); 430 } 431 432 // get HBA_PXIS value 433 unsigned int status = _hba_get_register( channel, HBA_PXIS ); 434 435 // reset HBA_PXIS 436 _hba_set_register( channel, HBA_PXIS, 0 ); 437 438 return status; 439 } 515 440 516 441 // Local Variables: -
soft/giet_vm/giet_drivers/hba_driver.h
r289 r295 59 59 } hba_cmd_entry_t; 60 60 61 typedef struct hba_cmd_table_s // size = 256 bytes61 typedef struct hba_cmd_table_s // size = 4096 bytes 62 62 { 63 63 … … 97 97 /////////////////////////////////////////////////////////////////////////////////// 98 98 99 unsigned int _hba_write( unsigned int mode, 100 unsigned int lba, // logic bloc address on device 101 void* buffer, // memory buffer base address 102 unsigned int count ); // number of blocs 99 extern unsigned int _hba_init ( unsigned int channel ); 103 100 104 unsigned int _hba_read ( unsigned int mode, 105 unsigned int lba, // logic bloc address on device 106 void* buffer, // memory buffer base address 107 unsigned int count ); // number of blocks 101 extern unsigned int _hba_write( unsigned int channel, // channel index 102 unsigned int mode, // BOOT / KERNEL / USER 103 unsigned int lba, // logic bloc address on device 104 unsigned long long paddr, // memory buffer base address 105 unsigned int count ); // number of blocs 108 106 109 unsigned int _hba_init ( unsigned int channel ); 107 extern unsigned int _hba_read ( unsigned int channel, // channel index 108 unsigned int mode, // BOOT / KERNEL / USER 109 unsigned int lba, // logic bloc address on device 110 unsigned long long paddr, // memory buffer base address 111 unsigned int count ); // number of blocks 110 112 111 unsigned int _hba_get_status( unsigned int channel, 112 unsigned int* status ); 113 extern unsigned int _hba_get_status( unsigned int channel ); 113 114 114 unsigned int _hba_reset_status( unsigned int channel ); 115 116 unsigned int _hba_get_block_size (); 115 extern unsigned int _hba_get_block_size (); 117 116 118 117 -
soft/giet_vm/giet_drivers/icu_driver.c
r263 r295 70 70 71 71 #if USE_XICU 72 _p uts("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n");72 _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n"); 73 73 return 1; 74 74 #else … … 98 98 99 99 #if USE_XICU 100 _p uts("[GIET ERROR] _icu_get_index() should not be used if USE_XICU is set\n");100 _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n"); 101 101 return 1; 102 102 #else -
soft/giet_vm/giet_drivers/ioc_driver.c
r289 r295 7 7 /////////////////////////////////////////////////////////////////////////////////// 8 8 // The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel. 9 // This driver supports the SocLib vci_block_device component, that is 10 // a single channel, block oriented, external storage contrÃŽler. 11 // 12 // It can exist only one block-device controler in the architecture. 13 // 14 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function, 15 // that is always blocking. The _ioc_access function will call the read or 16 // write function in the driver of the choosen IOC peripheral, which can be for 17 // now: BDV, HBA and SPI. This function can be called in 4 modes: 18 // 19 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address 20 // as a physical address (as the page tables are not build). This mode is 21 // used by the boot code to load the map.bin file into memory. 22 // 23 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to 24 // compute the buffer physical address. This mode is used by the boot code to 25 // load the various .elf files into memory. 26 // 27 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to 28 // compute the buffer physical address. There is no checking of user access 29 // right to the memory buffer. This mode must be used to access IOC, for an 30 // "open" system call. 31 // 32 // - In USER mode, the _ioc_access() function makes a V2P translation to 33 // compute the buffer physical address. The user access right to the memory 34 // buffer must be checked. This mode must be used to access IOC, for a 35 // "read/write" system call. 9 // 10 // This abstact driver define a generic API, supporting various physical 11 // block device controlers, including: 12 // - vci_block_device : single channel) => bdv_driver 13 // - vci_ahci : multi channels => hba_driver 14 // - sd_card : single channel => sdc_driver 15 // - ramdisk (single channel meory mapped virtual disk) => rdk_driver 16 // 17 // It can exist only one block-device type in the architecture, that must be 18 // defined by one of the following configuration variables in hard_config.h file: 19 // USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK. 20 // 21 // Any physical driver xxx must provide the following API: 22 // - _xxx_init() 23 // - _xxx_read() 24 // - _xxx_write() 25 // - _xxx_get_status() 26 // - _xxx_get_block_size() 27 // The "channel" parameter is no transmited to single channel devices. 28 // 29 // The _ioc_read() and _ioc_write() functions are always blocking for 30 // the calling user program. 31 // 32 // These functions compute the physical address of the memory buffer before 33 // calling the proper physical device. They can be called in 3 modes: 34 // 35 // - In BOOT mode, these functions use the buffer virtual address 36 // as a physical address if the MMU is not activated. 37 // They make a V2P translation if the MMU is activated. 38 // This mode is used to load the map.bin file (before memory activation), 39 // or to load the various .elf files (after MMU activation). 40 // 41 // - In KERNEL mode, these functions make a V2P translation to 42 // compute the buffer physical address. 43 // There is no checking of user access right to the memory buffer. 44 // This mode must be used for an "open" system call. 45 // 46 // - In USER mode, these functions make a V2P translation to 47 // compute the buffer physical address. 48 // The user access right to the memory buffer are checked. 49 // This mode must be used for a "read" or "write" system call. 36 50 // 37 51 // The IOMMU can be activated or not: … … 60 74 // if the IOMMU is not activated. 61 75 // An error code is returned if these conditions are not verified. 76 // 77 // The "seg_ioc_base" virtual base address of the segment containing the 78 // memory-mapped registers of the device must be defined in the giet_vsegs.ld file. 79 // If the RAMDISK is used, an extra memory segment with virtual base address 80 // "seg_ramdisk_base" must be defined in the giet_vsegs.ld file. 62 81 /////////////////////////////////////////////////////////////////////////////////// 63 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file. 82 // Implementation note: 83 // In order to share the code, the two _ioc_read() and _ioc_write() functions 84 // call the same _ioc_access() function. 64 85 /////////////////////////////////////////////////////////////////////////////////// 65 86 66 87 #include <giet_config.h> 67 88 #include <ioc_driver.h> 89 #include <bdv_driver.h> 90 #include <hba_driver.h> 91 #include <sdc_driver.h> 92 #include <rdk_driver.h> 68 93 #include <utils.h> 69 94 #include <tty_driver.h> … … 81 106 #endif 82 107 83 #if (USE_ BDV + USE_SPI + USE_HBA) != 184 # error: You must use only one IOC controller (BDV or SPI or HBA)85 #endif 86 87 #if USE_ BDV108 #if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1 109 # error: You must use only one IOC controller type (BDV or SPI or HBA or RDK) 110 #endif 111 112 #if USE_IOC_BDV 88 113 # include <bdv_driver.h> 89 114 #endif 90 115 91 #if USE_ SPI116 #if USE_IOC_SPI 92 117 # include <sdc_driver.h> 93 118 #endif 94 119 95 #if USE_ HBA120 #if USE_IOC_HBA 96 121 # include <hba_driver.h> 97 122 #endif 98 123 124 #if USE_IOC_RDK 125 # include <rdk_driver.h> 126 #endif 127 128 /////////////////////////////////////////////////////////////////////////////// 129 // IOC global variables 130 /////////////////////////////////////////////////////////////////////////////// 99 131 100 132 #define in_unckdata __attribute__((section (".unckdata"))) 101 133 102 ///////////////////// IOC global variables103 104 in_unckdata unsigned int _ioc_lock = 0;105 in_unckdata unsigned int _ioc_status = 0;106 in_unckdata volatile unsigned int _ioc_gtid;107 134 in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0; 108 135 in_unckdata volatile unsigned int _ioc_iommu_npages; 109 136 110 137 /////////////////////////////////////////////////////////////////////////////// 111 // _ioc_access()112 138 // This function transfer data between a memory buffer and the block device. 113 139 // The buffer lentgth is (count*block_size) bytes. 114 140 // Arguments are: 115 141 // - to_mem : from external storage to memory when non 0. 116 // - kernel : kernel buffer with identity mapping when non 0.142 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 117 143 // - lba : first block index on the external storage. 118 144 // - buf_vaddr : virtual base address of the memory buffer. … … 121 147 /////////////////////////////////////////////////////////////////////////////// 122 148 static unsigned int _ioc_access( unsigned int to_mem, 149 unsigned int channel, 123 150 unsigned int mode, 124 151 unsigned int lba, … … 128 155 129 156 #if GIET_DEBUG_IOC_DRIVER 130 _tty_get_lock( 0 ); 131 _puts("\n[IOC DEBUG] Enter _ioc_access() at cycle "); 132 _putd( _get_proctime() ); 133 _puts(" for processor "); 134 _putd( _get_procid() ); 135 _puts("\n - mode = "); 136 _putd( mode ); 137 _puts("\n - vaddr = "); 138 _putx( buf_vaddr ); 139 _puts("\n - sectors = "); 140 _putd( count ); 141 _puts("\n - lba = "); 142 _putx( lba ); 143 _puts("\n"); 144 _tty_release_lock( 0 ); 157 unsigned int procid = _get_procid(); 158 unsigned int cid = procid / NB_PROCS_MAX; 159 unsigned int lpid = procid % NB_PROCS_MAX; 160 unsigned int x = cid >> Y_WIDTH; 161 unsigned int y = cid & ((1<<Y_WIDTH) - 1); 162 163 _printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access() at cycle %d\n" 164 " - channel = %d\n" 165 " - mode = %d\n" 166 " - vaddr = %d\n" 167 " - sectors = %d\n" 168 " - lba = %d\n", 169 x, y, lpid, _get_proctime(), channel, mode, buf_vaddr, count, lba ); 145 170 #endif 146 171 … … 160 185 if ((unsigned int) buf_vaddr & 0x3) 161 186 { 162 _tty_get_lock( 0 ); 163 _puts("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n"); 164 _tty_release_lock( 0 ); 165 return 1; 187 _printf("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n"); 188 _exit(); 189 } 190 191 // check channel 192 if ( (USE_IOC_HBA == 0) && (channel > 0) ) 193 { 194 _printf("\n[GIET ERROR] in _ioc_access() : channel must be 0 when HBA not used\n"); 195 _exit(); 166 196 } 167 197 168 198 unsigned int length = count << 9; // count * 512 bytes 169 199 170 // computing targetbuffer physical address171 if ( mode == IOC_BOOT_PA_MODE )// identity mapping200 // computing memory buffer physical address 201 if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping 172 202 { 173 203 buf_paddr = (paddr_t)buf_vaddr; 174 204 } 175 else // V2P translation205 else // V2P translation required 176 206 { 177 207 // get page table virtual address 178 208 pt_vbase = _get_context_slot(CTX_PTAB_ID); 179 vpn_min = buf_vaddr >> 12;180 vpn_max = (buf_vaddr + length - 1) >> 12;209 vpn_min = buf_vaddr >> 12; 210 vpn_max = (buf_vaddr + length - 1) >> 12; 181 211 182 212 // loop on all virtual pages covering the user buffer 183 for (vpn = vpn_min, ix2 = 0 ; 184 vpn <= vpn_max ; 185 vpn++, ix2++ ) 213 for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ ) 186 214 { 187 215 // get ppn and flags for each vpn … … 193 221 if ( ko ) 194 222 { 195 _tty_get_lock( 0 ); 196 _puts("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n"); 197 _tty_release_lock( 0 ); 223 _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n"); 198 224 return 1; 199 225 } … … 201 227 if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) ) 202 228 { 203 _tty_get_lock( 0 ); 204 _puts("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n"); 205 _tty_release_lock( 0 ); 229 _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n"); 206 230 return 1; 207 231 } … … 209 233 if ( ((flags & PTE_W) == 0 ) && to_mem ) 210 234 { 211 _tty_get_lock( 0 ); 212 _puts("\n[GIET ERROR] in _ioc_access() : buffer not writable\n"); 213 _tty_release_lock( 0 ); 235 _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n"); 214 236 return 1; 215 237 } … … 223 245 if (ix2 > 511) // check buffer length < 2 Mbytes 224 246 { 225 _tty_get_lock( 0 ); 226 _puts("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n"); 227 _tty_release_lock( 0 ); 247 _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n"); 228 248 return 1; 229 249 } … … 242 262 if ((ppn - ppn_first) != ix2) 243 263 { 244 _tty_get_lock( 0 ); 245 _puts("[GIET ERROR] in _ioc_access() : split physical buffer\n"); 246 _tty_release_lock( 0 ); 264 _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n"); 247 265 return 1; 248 266 } … … 272 290 else // memory read : update data caches 273 291 { 274 // L1 cache : nothing to do ifL1 write-through292 // L1 cache : nothing to do for L1 write-through 275 293 276 294 // L2 cache (only if IOB used) … … 280 298 if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr; 281 299 282 #if USE_BDV 283 if (to_mem) error = _bdv_read (mode, lba, buf_paddr, count); 284 else error = _bdv_write(mode, lba, buf_paddr, count); 285 #elif USE_SPI 286 if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count); 287 else error = _sdc_write(mode, lba, buf_paddr, count); 288 #elif USE_HBA 289 if (to_mem) error = _hba_read (mode, lba, buf_paddr, count); 290 else error = _hba_write(mode, lba, buf_paddr, count); 300 /////////////////////////////////////////// 301 // select the proper physical device 302 /////////////////////////////////////////// 303 304 #if ( USE_IOC_BDV ) 305 306 #if GIET_DEBUG_IOC_DRIVER 307 _printf("\n[IOC DEBUG] Calling BDV driver\n"); 308 #endif 309 if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count); 310 else error = _bdv_write( mode, lba, buf_paddr, count); 311 312 #elif ( USE_IOC_SPI ) 313 314 #if GIET_DEBUG_IOC_DRIVER 315 _printf("\n[IOC DEBUG] Calling SPI driver\n"); 316 #endif 317 if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count); 318 else error = _sdc_write(mode, lba, buf_paddr, count); 319 320 #elif ( USE_IOC_HBA ) 321 322 #if GIET_DEBUG_IOC_DRIVER 323 _printf("\n[IOC DEBUG] Calling HBA driver\n"); 324 #endif 325 if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count); 326 else error = _hba_write(channel, mode, lba, buf_paddr, count); 327 328 #elif ( USE_IOC_RDK ) 329 330 #if GIET_DEBUG_IOC_DRIVER 331 _printf("\n[IOC DEBUG] Calling RDK driver\n"); 332 #endif 333 if (to_mem) error = _rdk_read (lba, buf_vaddr, count); 334 else error = _rdk_write(lba, buf_vaddr, count); 335 291 336 #endif 292 337 … … 295 340 296 341 /////////////////////////////////////////////////////////////////////////////// 297 // _ioc_init()298 342 // This function cheks block size, and activates the IOC interrupts. 299 343 // Return 0 for success. … … 301 345 unsigned int _ioc_init( unsigned int channel ) 302 346 { 303 #if USE_BDV 304 return _bdv_init( channel ); 305 #elif USE_SPI 306 return _sdc_init( channel ); 307 #elif USE_HBA 347 348 #if ( USE_IOC_BDV ) 349 350 return _bdv_init(); 351 352 #elif ( USE_IOC_SPI ) 353 354 return _sdc_init(); 355 356 #elif ( USE_IOC_HBA ) 357 308 358 return _hba_init( channel ); 309 #endif 359 360 #elif ( USE_IOC_RDK ) 361 362 return _rdk_init(); 363 364 #endif 365 310 366 } 311 367 312 368 /////////////////////////////////////////////////////////////////////////////// 313 // _ioc_read()314 369 // Transfer data from the block device to a memory buffer. 315 // - mode : BOOT / KERNEL / USER370 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 316 371 // - lba : first block index on the block device 317 372 // - buffer : base address of the memory buffer (must be word aligned) … … 319 374 // Returns 0 if success, > 0 if error. 320 375 /////////////////////////////////////////////////////////////////////////////// 321 unsigned int _ioc_read( unsigned int mode, 376 unsigned int _ioc_read( unsigned int channel, 377 unsigned int mode, 322 378 unsigned int lba, 323 379 void* buffer, … … 325 381 { 326 382 return _ioc_access( 1, // read access 383 channel, 327 384 mode, 328 385 lba, … … 332 389 333 390 /////////////////////////////////////////////////////////////////////////////// 334 // _ioc_write()335 391 // Transfer data from a memory buffer to the block device. 336 // - mode : BOOT / KERNEL / USER392 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 337 393 // - lba : first block index on the block device 338 394 // - buffer : base address of the memory buffer (must be word aligned) … … 340 396 // Returns 0 if success, > 0 if error. 341 397 /////////////////////////////////////////////////////////////////////////////// 342 unsigned int _ioc_write( unsigned int mode, 398 unsigned int _ioc_write( unsigned int channel, 399 unsigned int mode, 343 400 unsigned int lba, 344 401 const void* buffer, … … 346 403 { 347 404 return _ioc_access( 0, // write access 405 channel, 348 406 mode, 349 407 lba, … … 353 411 354 412 /////////////////////////////////////////////////////////////////////////////// 355 // _ioc_get_status()356 413 // This function returns in the status variable, the transfert status, and 357 414 // acknowledge the IRQ if the IOC controler is not busy. 358 415 // Returns 0 if success, > 0 if error 359 416 /////////////////////////////////////////////////////////////////////////////// 360 unsigned int _ioc_get_status( unsigned int channel, 361 unsigned int* status ) 362 { 363 #if USE_BDV 364 return _bdv_get_status(channel, status); 365 #elif USE_SPI 366 return _sdc_get_status(channel, status); 367 #elif USE_HBA 368 return _hba_get_status(channel, status); 369 #endif 417 unsigned int _ioc_get_status( unsigned int channel ) 418 { 419 420 #if ( USE_IOC_BDV ) 421 422 return _bdv_get_status( ); 423 424 #elif ( USE_IOC_SPI ) 425 426 return _sdc_get_status( ); 427 428 #elif ( USE_IOC_HBA ) 429 430 return _hba_get_status( channel ); 431 432 #elif ( USE_IOC_RDK ) 433 434 _printf("[GIET ERROR] _ioc_get_status() should not be called"); 435 _printf(" when RAMDISK is used...\n"); 436 _exit(); 437 438 return 0; 439 440 #endif 441 370 442 } 371 443 372 444 /////////////////////////////////////////////////////////////////////////////// 373 // _ioc_get_block_size()374 445 // This function returns the block_size with which the IOC has been configured. 375 446 /////////////////////////////////////////////////////////////////////////////// 376 447 unsigned int _ioc_get_block_size() 377 448 { 378 #if USE_BDV 449 450 #if ( USE_IOC_BDV ) 451 379 452 return _bdv_get_block_size(); 380 #elif USE_SPI 453 454 #elif ( USE_IOC_SPI ) 455 381 456 return _sdc_get_block_size(); 382 #elif USE_HBA 457 458 #elif ( USE_IOC_HBA ) 459 383 460 return _hba_get_block_size(); 384 #endif 461 462 #elif ( USE_IOC_RDK ) 463 464 return 512; 465 466 #endif 467 385 468 } 386 469 -
soft/giet_vm/giet_drivers/ioc_driver.h
r289 r295 13 13 /////////////////////////////////////////////////////////////////////////////////// 14 14 15 enum IOC_registers16 {17 BLOCK_DEVICE_BUFFER,18 BLOCK_DEVICE_LBA,19 BLOCK_DEVICE_COUNT,20 BLOCK_DEVICE_OP,21 BLOCK_DEVICE_STATUS,22 BLOCK_DEVICE_IRQ_ENABLE,23 BLOCK_DEVICE_SIZE,24 BLOCK_DEVICE_BLOCK_SIZE,25 BLOCK_DEVICE_BUFFER_EXT,26 };27 enum IOC_operations28 {29 BLOCK_DEVICE_NOOP,30 BLOCK_DEVICE_READ,31 BLOCK_DEVICE_WRITE,32 };33 enum IOC_status34 {35 BLOCK_DEVICE_IDLE,36 BLOCK_DEVICE_BUSY,37 BLOCK_DEVICE_READ_SUCCESS,38 BLOCK_DEVICE_WRITE_SUCCESS,39 BLOCK_DEVICE_READ_ERROR,40 BLOCK_DEVICE_WRITE_ERROR,41 BLOCK_DEVICE_ERROR,42 };43 15 enum IOC_driver_modes 44 16 { 45 IOC_BOOT_PA_MODE, // No V2P translation / Polling IOC_STATUS / no access checking 46 IOC_BOOT_VA_MODE, // V2P translation / Polling IOC_STATUS / no access checking 47 IOC_KERNEL_MODE, // V2P translation / Descheduling + IRQ / no access checking 48 IOC_USER_MODE, // V2P translation / Descheduling + IRQ / access checking 17 IOC_BOOT_MODE = 0, // Polling IOC_STATUS / no access right checking 18 IOC_KERNEL_MODE = 1, // Descheduling + IRQ / no access right checking 19 IOC_USER_MODE = 2, // Descheduling + IRQ / access right checking 49 20 }; 50 21 51 22 /////////////////////////////////////////////////////////////////////////////////// 52 // IOC access functions and variables (vci_block_device)23 // IOC global variables (generic disk controller) 53 24 /////////////////////////////////////////////////////////////////////////////////// 54 25 55 extern unsigned int _ioc_lock;56 extern unsigned int _ioc_status;57 extern volatile unsigned int _ioc_gtid;58 26 extern volatile unsigned int _ioc_iommu_ix1; 59 27 extern volatile unsigned int _ioc_iommu_npages; 60 28 29 /////////////////////////////////////////////////////////////////////////////////// 30 // IOC access functions (generic disk controller) 31 /////////////////////////////////////////////////////////////////////////////////// 32 61 33 extern unsigned int _ioc_init( unsigned int channel ); 62 34 63 extern unsigned int _ioc_write( unsigned int mode, 35 extern unsigned int _ioc_write( unsigned int channel, 36 unsigned int mode, 64 37 unsigned int lba, 65 38 const void* buffer, 66 39 unsigned int count ); 67 40 68 extern unsigned int _ioc_read( unsigned int mode, 41 extern unsigned int _ioc_read( unsigned int channel, 42 unsigned int mode, 69 43 unsigned int lba, 70 44 void* buffer, 71 45 unsigned int count ); 72 46 73 extern unsigned int _ioc_get_status( unsigned int channel, 74 unsigned int* status ); 47 extern unsigned int _ioc_get_status( unsigned int channel ); 75 48 76 49 extern unsigned int _ioc_get_block_size(); -
soft/giet_vm/giet_drivers/mmc_driver.c
r263 r295 57 57 if ( (x >= X_SIZE) || (y >= Y_SIZE) ) 58 58 { 59 _puts("\n[GIET ERROR] in _memc_inval() : illegal cluster index["); 60 _putd( x ); 61 _puts(","); 62 _putd( y ); 63 _puts("]\n"); 64 _puts(" - paddr = "); 65 _putl( buf_paddr ); 66 _puts("\n - cluster_xy = "); 67 _putx( cluster_xy ); 68 _puts("\n"); 59 _printf("\n[GIET ERROR] in _memc_inval() : illegal cluster_xy for paddr %l\n", 60 buf_paddr ); 69 61 _exit(); 70 62 } … … 102 94 if ( (x >= X_SIZE) || (y >= Y_SIZE) ) 103 95 { 104 _puts("\n[GIET ERROR] in _memc_sync() : illegal cluster index["); 105 _putd( x ); 106 _puts(","); 107 _putd( y ); 108 _puts("]\n"); 109 _puts(" - paddr = "); 110 _putl( buf_paddr ); 111 _puts("\n - cluster_xy = "); 112 _putx( cluster_xy ); 113 _puts("\n"); 96 _printf( "\n[GIET ERROR] in _memc_sync() : illegal cluster_xy for paddr %l\n", 97 buf_paddr ); 114 98 _exit(); 115 99 } -
soft/giet_vm/giet_drivers/mwr_driver.c
r263 r295 56 56 paddr_t channel_pbase ) 57 57 { 58 _p uts(" [GIET_ERROR] _mwr_hw_init() function not supported yet\n");58 _printf(" [GIET_ERROR] _mwr_hw_init() function not supported yet\n"); 59 59 _exit(); 60 60 -
soft/giet_vm/giet_drivers/nic_driver.c
r258 r295 56 56 #define in_unckdata __attribute__((section (".unckdata"))) 57 57 58 /////////////////////////////////////////////////////////////////////////////// 59 // This low_level function returns the value contained in register (index). 60 /////////////////////////////////////////////////////////////////////////////// 61 unsigned int _nic_get_register( unsigned int channel, 62 unsigned int index ) 63 { 64 unsigned int* vaddr = (unsigned int*)&seg_nic_base + 65 NIC_CHANNEL_SPAN*channel + index; 66 return _io_extended_read( vaddr ); 67 } 68 69 /////////////////////////////////////////////////////////////////////////////// 70 // This low-level function set a new value in register (index). 71 /////////////////////////////////////////////////////////////////////////////// 72 void _nic_set_register( unsigned int channel, 73 unsigned int index, 74 unsigned int value ) 75 { 76 unsigned int* vaddr = (unsigned int*)&seg_nic_base + 77 NIC_CHANNEL_SPAN*channel + index; 78 _io_extended_write( vaddr, value ); 79 } 80 58 81 ////////////////////////////////////////////////////////////////////////////////// 59 // _nic_sync_write()60 82 // Transfer data from an memory buffer to the NIC device using a memcpy. 61 83 // - buffer : base address of the memory buffer. … … 65 87 unsigned int length ) 66 88 { 67 _p uts("[GIET ERROR] _nic_sync_write function not implemented\n");89 _printf("[GIET ERROR] _nic_sync_write function not implemented\n"); 68 90 _exit(); 69 91 … … 73 95 } 74 96 ////////////////////////////////////////////////////////////////////////////////// 75 // _nic_sync_read()76 97 // Transfer data from the NIC device to a memory buffer using a memcpy. 77 98 // - buffer : base address of the memory buffer. … … 81 102 unsigned int length ) 82 103 { 83 _p uts("[GIET ERROR] _nic_sync_read function not implemented\n");104 _printf("[GIET ERROR] _nic_sync_read function not implemented\n"); 84 105 _exit(); 85 106 … … 89 110 } 90 111 ////////////////////////////////////////////////////////////////////////////////// 91 // _nic_cma_start()92 112 // Returns 0 if success, > 0 if error. 93 113 ////////////////////////////////////////////////////////////////////////////////// 94 114 unsigned int _nic_cma_start( ) 95 115 { 96 _p uts("[GIET ERROR] _nic_cma_start functionnot implemented\n");116 _printf("[GIET ERROR] _nic_cma_start() not implemented\n"); 97 117 _exit(); 98 118 … … 101 121 } 102 122 ////////////////////////////////////////////////////////////////////////////////// 103 // _nic_cma_stop()104 123 // Returns 0 if success, > 0 if error. 105 124 ////////////////////////////////////////////////////////////////////////////////// 106 125 unsigned int _nic_cma_stop() 107 126 { 108 _p uts("[GIET ERROR] _nic_cma_stop functionnot implemented\n");127 _printf("[GIET ERROR] _nic_cma_stop() not implemented\n"); 109 128 _exit(); 110 129 … … 113 132 } 114 133 134 ////////////////////////////////////////////////////////////////////////////////// 135 // This ISR handles IRQx from a NIC RX channeL 136 ////////////////////////////////////////////////////////////////////////////////// 137 void _nic_rx_isr( unsigned int irq_type, 138 unsigned int irq_id, 139 unsigned int channel ) 140 { 141 _printf("[GIET ERROR] _nic_rx_isr() not implemented\n"); 142 _exit(); 143 } 144 145 ////////////////////////////////////////////////////////////////////////////////// 146 // This ISR handles IRQx from a NIC RX channeL 147 ////////////////////////////////////////////////////////////////////////////////// 148 void _nic_tx_isr( unsigned int irq_type, 149 unsigned int irq_id, 150 unsigned int channel ) 151 { 152 _printf("[GIET ERROR] _nic_tx_isr() not implemented\n"); 153 _exit(); 154 } 115 155 116 156 // Local Variables: -
soft/giet_vm/giet_drivers/nic_driver.h
r258 r295 8 8 #ifndef _GIET_NIC_DRIVERS_H_ 9 9 #define _GIET_NIC_DRIVERS_H_ 10 11 /////////////////////////////////////////////////////////////////////////////////// 12 // NIC Registers (vci_multi_nic) 13 /////////////////////////////////////////////////////////////////////////////////// 14 15 enum SoclibMultiNicHyperviseurRegisters { 16 NIC_G_VIS = 0, // bitfield : bit N = 0 -> channel N disabled 17 NIC_G_ON = 1, // boolean : NIC component activated 18 NIC_G_NB_CHAN = 2, // Number of channels present in this NIC (read only) 19 NIC_G_BC_ENABLE = 3, // boolean : Enable Broadcast if non zero 20 NIC_G_TDM_ENABLE = 4, // boolean : TDM Scheduler if non zero 21 NIC_G_TDM_PERIOD = 5, // TDM time slot value 22 NIC_G_BYPASS_ENABLE = 6, // boolean : Enable bypass for TX packets 23 // alignment 24 NIC_G_MAC_4 = 8, // channel mac address 32 LSB bits array[8] 25 NIC_G_MAC_2 = 16, // channel mac address 16 MSB bits array[8] 26 // alignment 27 NIC_G_NPKT_RX_G2S_RECEIVED = 32, // number of packets received on GMII RX port 28 NIC_G_NPKT_RX_G2S_DISCARDED = 33, // number of RX packets discarded by RX_G2S FSM 29 30 NIC_G_NPKT_RX_DES_SUCCESS = 34, // number of RX packets transmited by RX_DES FSM 31 NIC_G_NPKT_RX_DES_TOO_SMALL = 35, // number of discarded too small RX packets (<60B) 32 NIC_G_NPKT_RX_DES_TOO_BIG = 36, // number of discarded too big RX packets (>1514B) 33 NIC_G_NPKT_RX_DES_MFIFO_FULL = 37, // number of discarded RX packets because fifo full 34 NIC_G_NPKT_RX_DES_CRC_FAIL = 38, // number of discarded RX packets because CRC32 failure 35 36 NIC_G_NPKT_RX_DISPATCH_RECEIVED = 39, // number of packets received by RX_DISPATCH FSM 37 NIC_G_NPKT_RX_DISPATCH_BROADCAST = 40, // number of broadcast RX packets received 38 NIC_G_NPKT_RX_DISPATCH_DST_FAIL = 41, // number of discarded RX packets for DST MAC not found 39 NIC_G_NPKT_RX_DISPATCH_CH_FULL = 42, // number of discarded RX packets for channel full 40 41 NIC_G_NPKT_TX_DISPATCH_RECEIVED = 43, // number of packets received by TX_DISPATCH FSM 42 NIC_G_NPKT_TX_DISPATCH_TOO_SMALL = 44, // number of discarded too small TX packets (<60B) 43 NIC_G_NPKT_TX_DISPATCH_TOO_BIG = 45, // number of discarded too big TX packets (>1514B) 44 NIC_G_NPKT_TX_DISPATCH_SRC_FAIL = 46, // number of discarded TX packets for SRC MAC failed 45 NIC_G_NPKT_TX_DISPATCH_BROADCAST = 47, // number of broadcast TX packets received 46 NIC_G_NPKT_TX_DISPATCH_BYPASS = 48, // number of bypassed TX->RX packets 47 NIC_G_NPKT_TX_DISPATCH_TRANSMIT = 49, // number of transmit TX packets 48 49 NIC_CHANNEL_SPAN = 0x2000, 50 }; 51 52 ///////////////////////////////////////////////////////////////////// 53 // A container descriptor has the following form: 54 // LOW WORD : Container LSB base address 55 // HIGH WORD: Container status (leftmost bit), '1' means full 56 // Base address MSB extension, if needed (right aligned) 57 ////////////////////////////////////////////////////////////////////// 58 enum SoclibMultiNicChannelRegisters 59 { 60 NIC_RX_DESC_LO_0 = 0, // RX_0 descriptor low word (Read/Write) 61 NIC_RX_DESC_HI_0 = 1, // RX_0 descriptor high word (Read/Write) 62 NIC_RX_DESC_LO_1 = 2, // RX_1 descriptor low word (Read/Write) 63 NIC_RX_DESC_HI_1 = 3, // RX_1 descriptor high word (Read/Write) 64 NIC_TX_DESC_LO_0 = 4, // TX_0 descriptor low word (Read/Write) 65 NIC_TX_DESC_HI_0 = 5, // TX_0 descriptor high word (Read/Write) 66 NIC_TX_DESC_LO_1 = 6, // TX_1 descriptor low word (Read/Write) 67 NIC_TX_DESC_HI_1 = 7, // TX_1 descriptor high word (Read/Write) 68 NIC_MAC_4 = 8, // channel mac address 32 LSB bits (Read Only) 69 NIC_MAC_2 = 9, // channel mac address 16 LSB bits (Read Only) 70 NIC_RX_RUN = 10, // RX packets can be received (write_only) 71 NIC_TX_RUN = 11, // TX packets can be transmitted (write_only) 72 }; 10 73 11 74 /////////////////////////////////////////////////////////////////////////////////// … … 23 86 extern unsigned int _nic_cma_stop(); 24 87 88 extern void _nic_rx_isr( unsigned int irq_type, 89 unsigned int irq_id, 90 unsigned int channel ); 91 92 extern void _nic_tx_isr( unsigned int irq_type, 93 unsigned int irq_id, 94 unsigned int channel ); 95 25 96 /////////////////////////////////////////////////////////////////////////////////// 26 97 -
soft/giet_vm/giet_drivers/sdc_driver.c
r289 r295 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 7 8 #include <sdc_driver.h> 9 #include <tty_driver.h> 8 10 #include <utils.h> 9 11 … … 179 181 if ( sdcard_rsp != 0x01 ) 180 182 { 181 182 _puts("card CMD0 failed "); 183 _printf("[SDC ERROR] card CMD0 failed\n"); 183 184 return sdcard_rsp; 184 185 } … … 196 197 if (!SDCARD_CHECK_R1_VALID(sdcard_rsp)) 197 198 { 198 _p uts("card CMD8 failed");199 _printf("[SDC ERROR] card CMD8 failed\n"); 199 200 return sdcard_rsp; 200 201 } … … 206 207 ersp = (ersp << 8) | _sdc_receive_char(); 207 208 ersp = (ersp << 8) | _sdc_receive_char(); 208 if ((ersp & 0xffff) != 0x0101) { 209 if ((ersp & 0xffff) != 0x0101) 210 { 209 211 // voltage mismatch 210 _puts("card CMD8 mismatch: "); 211 _putx(ersp); 212 _printf("[SDC ERROR] card CMD8 mismatch : ersp = %x\n"); 212 213 return sdcard_rsp; 213 214 } 214 _p uts("v2 or later ");215 _printf("[SDC WARNING] v2 or later "); 215 216 sdcard.sdhc = 1; 216 217 } … … 218 219 { 219 220 // other error 220 _p uts("card CMD8 error");221 _printf("[SDC ERROR] card CMD8 error\n"); 221 222 return sdcard_rsp; 222 223 } … … 249 250 if (sdcard_rsp) 250 251 { 251 _p uts("SD ACMD41 failed");252 _printf("[SDC ERROR] ACMD41 failed\n"); 252 253 return sdcard_rsp; 253 254 } … … 263 264 if (sdcard_rsp) 264 265 { 265 _p uts("SD CMD58 failed");266 _printf("[SDC ERROR] CMD58 failed\n"); 266 267 return sdcard_rsp; 267 268 } … … 272 273 if (ersp & 0x40000000) 273 274 { 274 _puts("SDHC "); 275 } else 275 _printf(" SDHC "); 276 } 277 else 276 278 { 277 279 sdcard.sdhc = 0; … … 279 281 _sdc_disable(); 280 282 } 281 _p uts("card detected");283 _printf("card detected\n"); 282 284 return 0; 283 285 } … … 334 336 // Returns 0 if success, other value if failure 335 337 /////////////////////////////////////////////////////////////////////////////// 336 unsigned int _sdc_init( unsigned int channel)338 unsigned int _sdc_init() 337 339 { 338 340 spi = (struct spi_dev*) &seg_ioc_base; … … 355 357 while(1) 356 358 { 357 _p uts("Trying to initialize SD card...");358 359 sdcard_rsp = _sdc_open( channel );359 _printf("[SDC WARNING] Trying to initialize SD card...\n"); 360 361 sdcard_rsp = _sdc_open( 0 ); // only channel 0 360 362 if (sdcard_rsp == 0) 361 363 { 362 _p uts("OK\n");364 _printf("OK\n"); 363 365 break; 364 366 } 365 367 366 _p uts("KO\n");368 _printf("KO\n"); 367 369 368 370 for (i = 0; i < 1000; i++); … … 370 372 if (++iter >= SDCARD_RESET_ITER_MAX) 371 373 { 372 _puts("\nERROR: During SD card reset to IDLE state\n" 373 "/ card response = "); 374 _putx(sdcard_rsp); 375 _puts("\n"); 374 _printf("\n[SDC ERROR] During SD card reset to IDLE state " 375 "/ card response = %x\n", sdcard_rsp ); 376 376 _exit(); 377 377 } … … 382 382 if (sdcard_rsp) 383 383 { 384 _p uts("ERROR:During SD card blocklen initialization\n");384 _printf("[SDC ERROR] During SD card blocklen initialization\n"); 385 385 _exit(); 386 386 } … … 396 396 ); 397 397 398 _p uts("Finish block deviceinitialization\n\r");398 _printf("[SDC WARNING] Finish SD card initialization\n\r"); 399 399 400 400 return 0; … … 478 478 479 479 /////////////////////////////////////////////////////////////////////////////// 480 // _sdc_get_status()481 480 // Transfer data from memory buffer to SD card device. 482 481 // - channel: channel index … … 484 483 // Returns 0 if success, > 0 if error. 485 484 /////////////////////////////////////////////////////////////////////////////// 486 unsigned int _sdc_get_status( unsigned int channel , 487 unsigned int* status ) 488 { 489 *status = BLOCK_DEVICE_IDLE; 490 491 return 0; 492 } 493 494 /////////////////////////////////////////////////////////////////////////////// 495 // _sdc_get_block_size() 485 unsigned int _sdc_get_status() 486 { 487 _printf("[SDC ERROR] function _sdc_get_status() should not be called\n"); 488 _exit(); 489 490 return 0; // to avoid a warning 491 } 492 493 /////////////////////////////////////////////////////////////////////////////// 496 494 // Returns the block size in bytes of the SD card 497 495 /////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/sdc_driver.h
r289 r295 36 36 }; 37 37 38 unsigned int _sdc_init( unsigned int channel ); 39 38 unsigned int _sdc_init(); 40 39 41 40 unsigned int _sdc_read( unsigned int mode, … … 50 49 unsigned int count); 51 50 51 unsigned int _sdc_get_status(); 52 52 53 unsigned int _sdc_get_block_size(); 53 54 unsigned int _sdc_get_status( unsigned int channel ,55 unsigned int* status );56 54 57 55 -
soft/giet_vm/giet_drivers/tim_driver.c
r263 r295 18 18 // The global index is cluster_xy * (NB_PROCS_MAX + NB_TIM_CHANNELS) + local_id 19 19 // 20 // The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in the 21 // hard_config.h file. 22 // 23 // The register offsets must be defined in the hwr_mapping.h file. 20 // The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in hard_config.h file. 24 21 ///////////////////////////////////////////////////////////////////////////////////// 25 22 // The virtual base address of the segment associated to a channel is: … … 33 30 #include <giet_config.h> 34 31 #include <tim_driver.h> 32 #include <xcu_driver.h> 33 #include <tty_driver.h> 35 34 #include <utils.h> 36 35 … … 68 67 69 68 #if (NB_TIM_CHANNELS > 0) 70 in_unckdata volatile unsigned char _user_timer_event[ X_SIZE*Y_SIZE*NB_TIM_CHANNELS]71 = { [0 ... ((X_SIZE*Y_SIZE*NB_TIM_CHANNELS) - 1)] = 0 };69 in_unckdata volatile unsigned char _user_timer_event[(1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS] 70 = { [0 ... (((1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS) - 1)] = 0 }; 72 71 #endif 73 72 74 73 //////////////////////////////////////////////////////////////////////////////////// 75 // _timer_start()76 74 // This function activates a timer in the vci_timer component 77 75 // by writing in the proper register the period value. 78 76 // It can be used by both the kernel to initialise a "system" timer, 79 77 // or by a task (through a system call) to configure an "user" timer. 80 // Returns 0 if success, > 0 if error. 81 ////////////////////////////////////////////////////////////////////////////// 82 unsigned int _timer_start( unsigned int cluster_xy, 83 unsigned int local_id, 84 unsigned int period) 85 { 86 // parameters checking 87 unsigned int x = cluster_xy >> Y_WIDTH; 88 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 89 if (x >= X_SIZE) return 1; 90 if (y >= Y_SIZE) return 1; 91 if (local_id >= NB_TIM_CHANNELS) return 1; 78 /////////////////////////////////////////////////////////////////////////////////// 79 void _timer_start( unsigned int cluster_xy, 80 unsigned int local_id, 81 unsigned int period) 82 { 83 #if NB_TIM_CHANNELS 84 85 // parameters checking 86 unsigned int x = cluster_xy >> Y_WIDTH; 87 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 88 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) ) 89 { 90 _printf("[GIET ERROR] in _timer_start()\n"); 91 _exit(); 92 } 92 93 93 94 unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + … … 96 97 timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period; 97 98 timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3; 98 return 0; 99 } 100 101 ////////////////////////////////////////////////////////////////////////////// 102 // _timer_stop() 99 100 #else 101 _printf("[GIET ERROR] _timer_start() should not be called when NB_TIM_CHANNELS is 0\n"); 102 _exit(); 103 #endif 104 } 105 106 ////////////////////////////////////////////////////////////////////////////// 103 107 // This function desactivates a timer in the vci_timer component 104 108 // by writing in the proper register. 105 109 // Returns 0 if success, > 0 if error. 106 110 ////////////////////////////////////////////////////////////////////////////// 107 unsigned int _timer_stop( unsigned int cluster_xy, 108 unsigned int local_id) 109 { 110 // parameters checking 111 unsigned int x = cluster_xy >> Y_WIDTH; 112 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 113 if (x >= X_SIZE) return 1; 114 if (y >= Y_SIZE) return 1; 115 if (local_id >= NB_TIM_CHANNELS) return 1; 111 void _timer_stop( unsigned int cluster_xy, 112 unsigned int local_id) 113 { 114 #if NB_TIM_CHANNELS 115 116 // parameters checking 117 unsigned int x = cluster_xy >> Y_WIDTH; 118 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 119 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) ) 120 { 121 _printf("[GIET ERROR] in _timer_stop()\n"); 122 _exit(); 123 } 116 124 117 125 unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + … … 119 127 120 128 timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0; 121 return 0; 122 } 123 124 ////////////////////////////////////////////////////////////////////////////// 125 // _timer_reset_irq() 129 130 #else 131 _printf("[GIET ERROR] _timer_stop() should not be called when NB_TIM_CHANNELS is 0\n"); 132 _exit(); 133 #endif 134 } 135 136 ////////////////////////////////////////////////////////////////////////////// 126 137 // This function acknowlegge a timer interrupt in the vci_timer 127 138 // component by writing in the proper register. … … 130 141 // Returns 0 if success, > 0 if error. 131 142 ////////////////////////////////////////////////////////////////////////////// 132 unsigned int _timer_reset_irq( unsigned int cluster_xy, 133 unsigned int local_id ) 134 { 135 // parameters checking 136 unsigned int x = cluster_xy >> Y_WIDTH; 137 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 138 if (x >= X_SIZE) return 1; 139 if (y >= Y_SIZE) return 1; 140 if (local_id >= NB_TIM_CHANNELS) return 1; 143 void _timer_reset_irq( unsigned int cluster_xy, 144 unsigned int local_id ) 145 { 146 #if NB_TIM_CHANNELS 147 148 // parameters checking 149 unsigned int x = cluster_xy >> Y_WIDTH; 150 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 151 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) ) 152 { 153 _printf("[GIET ERROR] in _timer_reset_irq()\n"); 154 _exit(); 155 } 141 156 142 157 unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + … … 144 159 145 160 timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0; 146 return 0; 161 162 #else 163 _printf("[GIET ERROR] _timer_reset_irq() should not be called when NB_TIM_CHANNELS is 0\n"); 164 _exit(); 165 #endif 147 166 } 148 167 149 168 ///////////////////////////////////////////////////////////////////////////// 150 // _timer_reset_cpt()151 169 // This function resets the timer counter. To do so, we re-write the period 152 170 // in the proper register, what causes the count to restart. … … 156 174 // This function is called during a context switch (user or preemptive) 157 175 //////////////////////////////////////////////////////////////////////i////// 158 unsigned int _timer_reset_cpt( unsigned int cluster_xy, 159 unsigned int local_id) 160 { 161 // parameters checking 162 unsigned int x = cluster_xy >> Y_WIDTH; 163 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 164 if (x >= X_SIZE) return 1; 165 if (y >= Y_SIZE) return 1; 166 if (local_id >= NB_TIM_CHANNELS) return 1; 176 void _timer_reset_cpt( unsigned int cluster_xy, 177 unsigned int local_id) 178 { 179 #if NB_TIM_CHANNELS 180 181 // parameters checking 182 unsigned int x = cluster_xy >> Y_WIDTH; 183 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 184 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) ) 185 { 186 _printf("[GIET ERROR in _timer_reset_cpt()\n"); 187 _exit(); 188 } 167 189 168 190 // We suppose that the TIMER_MODE register value is 0x3 … … 172 194 unsigned int period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD]; 173 195 timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period; 174 return 0; 175 } 196 197 #else 198 _printf("[GIET ERROR] _timer_reset_cpt should not be called when NB_TIM_CHANNELS is 0\n"); 199 _exit(); 200 #endif 201 } 202 203 /////////////////////////////////////////////////////////////////////////////////// 204 // This ISR handles the IRQs generated by the "user" timers that are 205 // replicated in all clusters. 206 // The IRQs generated by the "system" timers should be handled by _isr_switch(). 207 // It can be a HWI or a PTI. 208 // The channel argument is the user timer local index. 209 // timer_global_id = cluster_id*(NB_TIM_CHANNELS) + channel 210 // The ISR acknowledges the IRQ and registers the event in the proper entry 211 // of the _user_timer_event[] array, and a log message is displayed on TTY0. 212 /////////////////////////////////////////////////////////////////////////////////// 213 void _timer_isr( unsigned int irq_type, // HWI / PTI 214 unsigned int irq_id, // index returned by XCU 215 unsigned int channel ) // user timer index 216 { 217 #if NB_TIM_CHANNELS 218 219 unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX; 220 221 // acknowledge IRQ depending on type 222 if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel ); 223 else _xcu_timer_reset_irq( cluster_xy, irq_id ); 224 225 // register the event 226 _user_timer_event[cluster_xy * NB_TIM_CHANNELS + channel] = 1; 227 228 // display a message on TTY 0 229 _printf("\n[GIET WARNING] User Timer IRQ at cycle %d / cluster = %x / channel = %d\n", 230 _get_proctime(), cluster_xy, channel ); 231 232 #else 233 _printf("[GIET ERROR] _timer_isr() should not be called when NB_TIM_CHANNELS == 0\n"); 234 _exit(); 235 #endif 236 } 237 176 238 177 239 -
soft/giet_vm/giet_drivers/tim_driver.h
r263 r295 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 7 8 #ifndef _GIET_TIM_DRIVER S_H_9 #define _GIET_TIM_DRIVER S_H_8 #ifndef _GIET_TIM_DRIVER_H_ 9 #define _GIET_TIM_DRIVER_H_ 10 10 11 11 /////////////////////////////////////////////////////////////////////////////////// … … 27 27 /////////////////////////////////////////////////////////////////////////////////// 28 28 29 extern volatile unsigned char _timer_event[]; 29 extern void _timer_start( unsigned int cluster_xy, 30 unsigned int local_id, 31 unsigned int period ); 30 32 31 extern unsigned int _timer_start( unsigned int cluster_xy, 32 unsigned int local_id, 33 unsigned int period ); 33 extern void _timer_stop( unsigned int cluster_xy, 34 unsigned int local_id ); 34 35 35 extern unsigned int _timer_stop( unsigned int cluster_xy,36 36 extern void _timer_reset_irq( unsigned int cluster_xy, 37 unsigned int local_id ); 37 38 38 extern unsigned int _timer_reset_irq( unsigned int cluster_xy,39 unsigned int local_id);39 extern void _timer_reset_cpt( unsigned int cluster_xy, 40 unsigned int local_id); 40 41 41 extern unsigned int _timer_reset_cpt( unsigned int cluster_xy, 42 unsigned int local_id); 42 extern void _timer_isr( unsigned int irq_type, 43 unsigned int irq_id, 44 unsigned int channel ); 43 45 44 46 /////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/tty_driver.c
r258 r295 8 8 // This driver supports the SocLib vci_multi_tty component. 9 9 // 10 // It can exist only one multi_tty controler in the architecture.11 //12 10 // The total number of TTY terminals must be defined by the configuration 13 11 // parameter NB_TTY_CHANNELS in the hard_config.h file. 14 //15 // The register offsets must be defined in the hwr_mapping.h file.16 12 // 17 13 // The "system" terminal is TTY[0]. … … 19 15 // as defined in the mapping_info data structure. The corresponding tty_id must 20 16 // be stored in the context of the task by the boot code. 21 ///////////////////////////////////////////////////////////////////////////////////22 // The virtual base address of the segment associated to a channel is:23 17 // 24 // seg_tty_base + TTY_SPAN * channel_id 25 // 26 // The seg_tty_base virtual base addresses must be defined in giet_vsegs.ld file. 18 // The seg_tty_base must be defined in giet_vsegs.ld file. 19 /////////////////////////////////////////////////////////////////////////////////// 20 // Implementation note: 21 // 22 // All physical accesses to device registers are done by the two 23 // _tty_get_register(), _tty_set_register() low-level functions, 24 // that are handling virtual / physical addressing. 27 25 /////////////////////////////////////////////////////////////////////////////////// 28 26 29 27 #include <giet_config.h> 30 28 #include <tty_driver.h> 29 #include <xcu_driver.h> 31 30 #include <ctx_handler.h> 32 31 #include <utils.h> … … 42 41 #define in_unckdata __attribute__((section (".unckdata"))) 43 42 44 ///////////////// TTY global variables 45 in_unckdata volatile unsigned char _tty_get_buf[NB_TTY_CHANNELS]; 46 in_unckdata volatile unsigned char _tty_get_full[NB_TTY_CHANNELS] 43 ////////////////////////////////////////////////////////////////////////////// 44 // TTY global variables 45 ////////////////////////////////////////////////////////////////////////////// 46 47 in_unckdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS]; 48 in_unckdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS] 47 49 = { [0 ... NB_TTY_CHANNELS - 1] = 0 }; 50 51 ////////////////////////////////////////////////////////////////////////////// 52 // This low level function returns the value of register (channel / index) 53 ////////////////////////////////////////////////////////////////////////////// 54 unsigned int _tty_get_register( unsigned int channel, 55 unsigned int index ) 56 { 57 unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index; 58 return _io_extended_read( vaddr ); 59 } 60 61 ////////////////////////////////////////////////////////////////////////////// 62 // This low level function set a new value in register (channel / index) 63 ////////////////////////////////////////////////////////////////////////////// 64 void _tty_set_register( unsigned int channel, 65 unsigned int index, 66 unsigned int value ) 67 { 68 unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index; 69 _io_extended_write( vaddr, value ); 70 } 48 71 49 72 ///////////////////////////////////////////////////////////////////////////////// 50 73 // This non-blocking function writes a character string from a fixed-length 51 // buffer to the TTY_WRITE register of a TTY terminal identified by the 52 // channel argument. If the channel argument is 0xFFFFFFFF, the channel 53 // index is obtained from the current taxk context. 54 // It doesn't use any interrupt. 74 // buffer to a TTY terminal identified by the channel argument. 75 // This function is intended to be used to handle a system call, and should 76 // not be used by the kernel for log messages on TTY 0. 77 // protecting exclusive access to the selected terminal. 78 // If channel argument is 0xFFFFFFFF, the TTY index is found in the task context. 55 79 // This is a non blocking call: it tests the TTY_STATUS register, and stops 56 80 // the transfer as soon as the TTY_STATUS[WRITE] bit is set. … … 62 86 unsigned int channel) // channel index 63 87 { 64 unsigned int nwritten; 65 unsigned int tty_id; 66 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 67 68 // compute tty channel 69 if( channel == 0xFFFFFFFF ) 70 { 71 tty_id = _get_context_slot(CTX_TTY_ID); 72 } 73 else 74 { 75 tty_id = (unsigned int)channel; 76 } 88 unsigned int nwritten; 89 90 // compute and check tty channel 91 if( channel == 0xFFFFFFFF ) channel = _get_context_slot(CTX_TTY_ID); 92 if( channel >= NB_TTY_CHANNELS ) return -1; 77 93 78 94 // write string to TTY channel … … 80 96 { 81 97 // check tty's status 82 if ((tty_address[tty_id * TTY_SPAN + TTY_STATUS] & 0x2) == 0x2) break; 83 _tty_write_data( tty_id, buffer[nwritten] ); 84 } 98 if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 ) break; 99 100 // write one byte 101 _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] ); 102 } 103 85 104 return nwritten; 86 105 } … … 92 111 // It uses the TTY_GET_IRQ[tty_id] interrupt and the buffer must have been 93 112 // filled by the TTY_ISR. 94 // It test the _tty_ get_full[tty_id] register, read the _tty_get_buf[tty_id]113 // It test the _tty_rx_full[tty_id] variable, read the _tty_rx_buf[tty_id] 95 114 // buffer, writes this character to the target buffer, and resets the 96 // _tty_ get_full[tty_id] register.115 // _tty_rx_full[tty_id] register. 97 116 // The length argument is not used. 98 117 ////////////////////////////////////////////////////////////////////////////// … … 103 122 unsigned int channel) // channel index 104 123 { 105 106 unsigned int tty_id; 107 108 // compute tty channel 109 if( channel == 0xFFFFFFFF ) 110 { 111 tty_id = _get_context_slot(CTX_TTY_ID); 112 } 113 else 114 { 115 tty_id = (unsigned int)channel; 116 } 124 // compute and check tty channel 125 if( channel == 0xFFFFFFFF ) channel = _get_context_slot(CTX_TTY_ID); 126 if( channel >= NB_TTY_CHANNELS ) return -1; 117 127 118 128 // read one character from TTY channel 119 if (_tty_ get_full[tty_id] == 0)129 if (_tty_rx_full[channel] == 0) 120 130 { 121 131 return 0; … … 123 133 else 124 134 { 125 *buffer = _tty_ get_buf[tty_id];126 _tty_ get_full[tty_id] = 0;135 *buffer = _tty_rx_buf[channel]; 136 _tty_rx_full[channel] = 0; 127 137 return 1; 128 138 } 129 139 } 130 ////////////////////////////////////////////////////////////////////////////// 131 132 ////////////////////////////////////////////////////////////////////////////// 133 // This function try to take the hardwired lock protecting exclusive access 134 // to TTY terminal identified by the channel argument. 140 141 ////////////////////////////////////////////////////////////////////////////// 142 // This function try to take the hardwired lock protecting 143 // exclusive access to TTY terminal identified by the "channel" argument. 144 // It enters a critical section before taking the lock, and save the SR value 145 // at address defined by the "save_sr_ptr" argument. 135 146 // It returns only when the lock has been successfully taken. 136 147 ////////////////////////////////////////////////////////////////////////////// 137 void _tty_get_lock( unsigned int channel )138 { 139 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 140 141 if( channel >= NB_TTY_CHANNELS )142 {143 _puts("[GIET ERROR] in _tty_get_lock() : illegal TTY index\n"); 144 _exit(); 145 } 146 147 while ( tty_address[channel * TTY_SPAN + TTY_CONFIG] ); 148 } 149 150 ////////////////////////////////////////////////////////////////////////////// 151 // This function releases the hardwired lock protecting exclusive access 152 // to TTY terminal identified by the channel argument. 153 ////////////////////////////////////////////////////////////////////////////// 154 void _tty_release_lock( unsigned int channel ) 155 { 156 unsigned int* tty_address = (unsigned int *) &seg_tty_base;157 158 if( channel >= NB_TTY_CHANNELS ) 159 { 160 _puts("[GIET ERROR] in _tty_release_lock() : illegal TTY index\n"); 161 _exit(); 162 } 163 164 tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0; 165 } 166 167 ////////////////////////////////////////////////////////////////////////////// 168 // This function returns the content of the TTY_READ register in the 169 // TTY terminal identified by the channel argument. 170 ////////////////////////////////////////////////////////////////////////////// 171 unsigned int _tty_read_data( unsigned int channel ) 172 { 173 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 174 175 if( channel >= NB_TTY_CHANNELS )176 {177 _ puts("[GIET ERROR] in _tty_read_data() : illegal TTY index\n");178 _exit();179 }180 181 return tty_address[channel * TTY_SPAN + TTY_READ];182 } 183 184 ////////////////////////////////////////////////////////////////////////////// 185 // This function returns the content of the TTY_STATUS register in the 186 // TTY terminal identified by the channel argument. 187 ////////////////////////////////////////////////////////////////////////////// 188 unsigned int _tty_get_status( unsigned int channel ) 189 { 190 unsigned int* tty_address = (unsigned int *) &seg_tty_base;191 192 if( channel >= NB_TTY_CHANNELS ) 193 { 194 _puts("[GIET ERROR] in _tty_get_status() : illegal TTY index\n");195 _exit(); 196 } 197 198 return tty_address[channel * TTY_SPAN + TTY_STATUS]; 199 } 200 201 ////////////////////////////////////////////////////////////////////////////// 202 // This function writes one character in the TTY_WRITE register in the 203 // TTY terminal identified by the channel argument. 204 ////////////////////////////////////////////////////////////////////////////// 205 void _tty_write_data( unsigned int channel, 206 char byte ) 207 { 208 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 209 210 if( channel >= NB_TTY_CHANNELS ) 211 { 212 _puts("[GIET ERROR] in _tty_write_data() : illegal TTY index\n"); 213 _exit();214 }215 216 tty_address[channel * TTY_SPAN + TTY_WRITE] = (unsigned int) byte;217 } 218 148 void _tty_get_lock( unsigned int channel, 149 unsigned int * save_sr_ptr ) 150 { 151 if( channel >= NB_TTY_CHANNELS ) _exit(); 152 _it_disable( save_sr_ptr ); 153 while ( _tty_get_register( channel, TTY_CONFIG ) ); // busy waiting 154 } 155 156 ////////////////////////////////////////////////////////////////////////////// 157 // This function releases the hardwired lock protecting 158 // exclusive access to TTY terminal identified by the channel argument. 159 // It exit the critical section after lock release, and restore SR value 160 // from address defined by the "save_sr_ptr" argument. 161 ////////////////////////////////////////////////////////////////////////////// 162 void _tty_release_lock( unsigned int channel, 163 unsigned int * save_sr_ptr ) 164 { 165 if( channel >= NB_TTY_CHANNELS ) _exit(); 166 167 _tty_set_register( channel, TTY_CONFIG, 0 ); 168 _it_restore( save_sr_ptr ); 169 } 170 171 /////////////////////////////////////////////////////////////////////////////////// 172 // This ISR handles the IRQ signaling that the RX buffer is full. 173 // IT can be an HWI or an SWI. 174 // There is one single multi_tty component controling all channels. 175 // There is one communication buffer _tty_rx_buf[i] and one synchronisation 176 // variable _tty_rx_full[i] per channel. 177 // A character is lost if the buffer is full when the ISR is executed. 178 /////////////////////////////////////////////////////////////////////////////////// 179 void _tty_rx_isr( unsigned int irq_type, // HWI / WTI 180 unsigned int irq_id, // index returned by XCU 181 unsigned int channel ) // TTY channel 182 { 183 unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX; 184 185 if ( irq_type == IRQ_TYPE_WTI ) // reset SWI in XCU if required 186 { 187 unsigned int value; 188 _xcu_get_wti_value( cluster_xy, irq_id, &value ); 189 } 190 191 // get character and reset TTY IRQ 192 _tty_rx_buf[channel] = _tty_get_register( channel, TTY_READ ); 193 194 #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlock 195 unsigned int x = cluster_xy >> Y_WIDTH; 196 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 197 unsigned int lpid = _get_procid() % NB_PROCS_MAX; 198 _puts("\n[IRQS DEBUG] Processor["); 199 _putd(x ); 200 _puts(","); 201 _putd(y ); 202 _puts(","); 203 _putd(lpid ); 204 _puts("] enters _tty_rx_isr() at cycle "); 205 _putd(_get_proctime() ); 206 _puts("\n read byte = "); 207 _putx(_tty_rx_buf[channel] ); 208 _puts("\n"); 209 #endif 210 211 // signals character available 212 _tty_rx_full[channel] = 1; 213 } 214 215 /////////////////////////////////////////////////////////////////////////////////// 216 // This ISR handles the IRQ signaling that the TX buffer is empty. 217 // IT can be an HWI or an SWI. 218 // There is one single multi_tty component controling all channels. 219 // There is one communication buffer _tty_rx_buf[i] and one synchronisation 220 // variable _tty_rx_full[i] per channel. 221 // A character is lost if the buffer is full when the ISR is executed. 222 /////////////////////////////////////////////////////////////////////////////////// 223 void _tty_tx_isr( unsigned int irq_type, // HWI / WTI 224 unsigned int irq_id, // index returned by XCU 225 unsigned int channel ) // TTY channel 226 { 227 _puts("\n[GIET ERROR] the _tty_tx_isr() is not implemented\n"); 228 _exit(); 229 } 219 230 220 231 // Local Variables: -
soft/giet_vm/giet_drivers/tty_driver.h
r258 r295 24 24 25 25 /////////////////////////////////////////////////////////////////////////////////// 26 // TTY access functions andvariables26 // TTY variables 27 27 /////////////////////////////////////////////////////////////////////////////////// 28 28 … … 31 31 extern volatile unsigned char _tty_get_full[]; 32 32 33 /////// rather high level access functions /////////////////////////////////////// 33 ////////////////////////////////////////////////////////////////////////////////// 34 // TTY access functions 35 ////////////////////////////////////////////////////////////////////////////////// 34 36 35 37 extern unsigned int _tty_write( const char* buffer, 36 unsigned int length, // number of characters37 unsigned int channel ); // channel index38 unsigned int length, 39 unsigned int channel ); 38 40 39 41 extern unsigned int _tty_read( char* buffer, 40 unsigned int length, // unused41 unsigned int channel ); // channel index42 unsigned int length, 43 unsigned int channel ); 42 44 43 /////// very low level access functions ////////////////////////////////////////// 45 extern void _tty_get_lock( unsigned int channel, 46 unsigned int* save_sr_ptr ); 44 47 45 extern void _tty_write_data( unsigned int channel, char byte ); 48 extern void _tty_release_lock( unsigned int channel, 49 unsigned int* save_sr_ptr ); 46 50 47 extern unsigned int _tty_read_data( unsigned int channel ); 51 extern void _tty_rx_isr( unsigned int irq_type, 52 unsigned int irq_id, 53 unsigned int channel ); 48 54 49 extern unsigned int _tty_get_status( unsigned int channel ); 50 51 extern void _tty_get_lock( unsigned int channel ); 52 53 extern void _tty_release_lock( unsigned int channel ); 55 extern void _tty_tx_isr( unsigned int irq_type, 56 unsigned int irq_id, 57 unsigned int channel ); 54 58 55 59 /////////////////////////////////////////////////////////////////////////////////// 60 // low-level access functions 61 /////////////////////////////////////////////////////////////////////////////////// 56 62 63 extern unsigned int _tty_get_register( unsigned int channel, 64 unsigned int index ); 65 66 extern void _tty_set_register( unsigned int channel, 67 unsigned int index, 68 unsigned int value ); 57 69 58 70 #endif -
soft/giet_vm/giet_drivers/xcu_driver.c
r281 r295 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.8 // This driver supports the SoCLib vci_xicu, that is a vectorised interrupt9 // controler supporting IPI (Inter Processor Interrupts) and integrated timers.10 //11 // It can exist several interrupt controller unit in the architecture12 // (one per cluster), and each one can contain several channels.13 // The number of XICU channels is equal to NB_PROCS_MAX, because there is14 // one private XICU channel per processor in a cluster.15 ////////////////////////////////////////////////////////////////////////////////16 // The virtual base address of the segment associated to the component is:17 //18 // seg_xcu_base + cluster_xy * vseg_cluster_increment19 //20 // The seg_xcu_base and vseg_cluster_increment values must be defined21 // in giet_vsegs.ld file.22 ////////////////////////////////////////////////////////////////////////////////23 7 24 8 #include <giet_config.h> … … 52 36 #endif 53 37 54 //////////////////////////////////////////////////////////////////////////////// 55 // _xcu_set_mask() 56 // This function set the mask register for the XICU channel identified by the 57 // cluster index and the processor index multiplied by the number of IRQ per 58 // processor. 38 39 //////////////////////////////////////////////////////////////////////////////// 40 // This function set the mask register for the IRQ type defined by "irq_type", 41 // and for the channel identified by the "cluster_xy" and "channel" arguments. 59 42 // All '1' bits are set / all '0' bits are not modified. 60 // Returns 0 if success, > 0 if error. 61 //////////////////////////////////////////////////////////////////////////////// 62 unsigned int _xcu_set_mask( unsigned int cluster_xy, 63 unsigned int irq_index, 64 unsigned int value, 65 unsigned int irq_type ) 66 { 67 // parameters checking 68 unsigned int x = cluster_xy >> Y_WIDTH; 69 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 70 if (x >= X_SIZE) return 1; 71 if (y >= Y_SIZE) return 1; 72 if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1; 73 74 #if USE_XICU 43 //////////////////////////////////////////////////////////////////////////////// 44 void _xcu_set_mask( unsigned int cluster_xy, 45 unsigned int channel, 46 unsigned int value, 47 unsigned int irq_type ) 48 { 49 #if USE_XICU 50 // parameters checking 51 unsigned int x = cluster_xy >> Y_WIDTH; 52 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 53 if (x >= X_SIZE) _exit(); 54 if (y >= Y_SIZE) _exit(); 55 if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 56 75 57 volatile unsigned int* xcu_address = 76 58 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 79 61 unsigned int func; 80 62 if (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE; 81 else if (irq_type == IRQ_TYPE_SWI) func = XICU_MSK_WTI_ENABLE; 82 else func = XICU_MSK_HWI_ENABLE; 83 xcu_address[XICU_REG(func,irq_index)] = value; 84 return 0; 85 #else 86 _tty_get_lock( 0 ); 87 _puts("[GIET ERROR] _xcu_set_mask should not be used if USE_XICU is not set\n"); 88 _tty_release_lock( 0 ); 89 return 1; 90 #endif 91 } 92 93 //////////////////////////////////////////////////////////////////////////////// 94 // _xcu_get_index() 95 // This function returns the index of the highest priority (smaller index) 96 // - active HWI (Hardware Interrupt), or 97 // - active PTI (Timer Interrupt), or 98 // - active SWI (Software Interrupt). 99 // The ICU channel is identified by the cluster index and the processor index 100 // multiplied by the number of IRQ per processor. 101 // Returns 0 if success, > 0 if error. 102 //////////////////////////////////////////////////////////////////////////////// 103 unsigned int _xcu_get_index( unsigned int cluster_xy, 104 unsigned int irq_index, 105 unsigned int * buffer) 106 { 107 // parameters checking 108 unsigned int x = cluster_xy >> Y_WIDTH; 109 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 110 if (x >= X_SIZE) return 1; 111 if (y >= Y_SIZE) return 1; 112 if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1; 113 114 #if USE_XICU 115 volatile unsigned int* xcu_address = 116 (unsigned int *) ((unsigned int)&seg_xcu_base + 117 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 118 119 unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,irq_index)]; 63 else if (irq_type == IRQ_TYPE_WTI) func = XICU_MSK_WTI_ENABLE; 64 else if (irq_type == IRQ_TYPE_HWI) func = XICU_MSK_HWI_ENABLE; 65 else 66 { 67 _printf("[GIET ERROR] _xcu_set_mask() receives illegal IRQ type\n"); 68 _exit(); 69 } 70 71 xcu_address[XICU_REG(func,channel)] = value; 72 73 #else 74 _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XICU not set\n"); 75 _exit(); 76 #endif 77 } 78 79 //////////////////////////////////////////////////////////////////////////////// 80 // This function returns the index and the type of the highest priority 81 // - active PTI (Timer Interrupt), then 82 // - active HWI (Hardware Interrupt), then 83 // - active WTI (Software Interrupt) 84 // As the hardware can define more than one IRQ per processor, but the GIET 85 // use only one, channel = lpid * IRQ_PER_PROCESSOR. 86 //////////////////////////////////////////////////////////////////////////////// 87 void _xcu_get_index( unsigned int cluster_xy, 88 unsigned int channel, 89 unsigned int * index, 90 unsigned int * irq_type ) 91 { 92 #if USE_XICU 93 // parameters checking 94 unsigned int x = cluster_xy >> Y_WIDTH; 95 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 96 if (x >= X_SIZE) _exit(); 97 if (y >= Y_SIZE) _exit(); 98 if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 99 100 volatile unsigned int* xcu_address = 101 (unsigned int *) ((unsigned int)&seg_xcu_base + 102 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 103 104 unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,channel)]; 120 105 unsigned int pti_ok = (prio & 0x00000001); 121 106 unsigned int hwi_ok = (prio & 0x00000002); 122 unsigned int swi_ok = (prio & 0x00000004);107 unsigned int wti_ok = (prio & 0x00000004); 123 108 unsigned int pti_id = (prio & 0x00001F00) >> 8; 124 109 unsigned int hwi_id = (prio & 0x001F0000) >> 16; 125 unsigned int swi_id = (prio & 0x1F000000) >> 24; 126 if (pti_ok) *buffer = pti_id; 127 else if (hwi_ok) *buffer = hwi_id; 128 else if (swi_ok) *buffer = swi_id; 129 else *buffer = 32; 130 return 0; 131 #else 132 _tty_get_lock( 0 ); 133 _puts("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n"); 134 _tty_release_lock( 0 ); 135 return 1; 136 #endif 137 } 138 139 //////////////////////////////////////////////////////////////////////////////// 140 // _xcu_send_ipi() 141 // This function can be used only in an architecture using XICU components. 142 // It writes the "wdata" value in the mailbox defined by the cluster index 143 // and the processor index. 144 // Giet-VM supports at most NB_PROCS_MAX mailboxes: 145 // (0 <= wti_index <= NB_PROCS_MAX-1) 146 // Returns 0 if success, > 0 if error. 147 //////////////////////////////////////////////////////////////////////////////// 148 unsigned int _xcu_send_ipi( unsigned int cluster_xy, 149 unsigned int wti_index, 150 unsigned int wdata ) 110 unsigned int wti_id = (prio & 0x1F000000) >> 24; 111 if (pti_ok) 112 { 113 *index = pti_id; 114 *irq_type = IRQ_TYPE_PTI; 115 } 116 else if (hwi_ok) 117 { 118 *index = hwi_id; 119 *irq_type = IRQ_TYPE_HWI; 120 } 121 else if (wti_ok) 122 { 123 *index = wti_id; 124 *irq_type = IRQ_TYPE_WTI; 125 } 126 else 127 { 128 *index = 32; 129 } 130 131 #else 132 _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n"); 133 _exit(); 134 #endif 135 } 136 137 //////////////////////////////////////////////////////////////////////////////// 138 // This function writes the "wdata" value in the mailbox defined 139 // by the "cluster_xy" and "wti_index" arguments. 140 //////////////////////////////////////////////////////////////////////////////// 141 void _xcu_send_wti( unsigned int cluster_xy, 142 unsigned int wti_index, 143 unsigned int wdata ) 151 144 { 152 // parameters checking 153 unsigned int x = cluster_xy >> Y_WIDTH;154 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);155 if (x >= X_SIZE) return 1;156 if ( y >= Y_SIZE) return 1;157 if ( wti_index >= NB_PROCS_MAX) return 1;158 159 #if USE_XICU 145 #if USE_XICU 146 // parameters checking 147 unsigned int x = cluster_xy >> Y_WIDTH; 148 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 149 if (x >= X_SIZE) _exit(); 150 if (y >= Y_SIZE) _exit(); 151 if (wti_index >= 32) _exit(); 152 160 153 volatile unsigned int* xcu_address = 161 154 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 163 156 164 157 xcu_address[XICU_REG(XICU_WTI_REG,wti_index)] = wdata; 165 return 0; 166 #else 167 _tty_get_lock( 0 ); 168 _puts("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n"); 169 _tty_release_lock( 0 ); 170 return 1; 158 159 #else 160 _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n"); 161 _exit(); 171 162 #endif 172 163 } 173 164 174 165 //////////////////////////////////////////////////////////////////////////////// 175 // _xcu_timer_start() 166 // This function returns the value contained in a WTI mailbox defined by 167 // the cluster_xy and "wti_index" arguments. This value is written in 168 // the "value" argument, and the corresponding WTI is acknowledged. 169 // returns 0 if success, > 0 if error. 170 //////////////////////////////////////////////////////////////////////////////// 171 void _xcu_get_wti_value( unsigned int cluster_xy, 172 unsigned int wti_index, 173 unsigned int * value ) 174 { 175 #if USE_XICU 176 // parameters checking 177 unsigned int x = cluster_xy >> Y_WIDTH; 178 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 179 if (x >= X_SIZE) _exit(); 180 if (y >= Y_SIZE) _exit(); 181 if (wti_index >= 32) _exit(); 182 183 volatile unsigned int* xcu_address = 184 (unsigned int *) ((unsigned int)&seg_xcu_base + 185 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 186 187 *value = xcu_address[XICU_REG(XICU_WTI_REG, wti_index)]; 188 189 #else 190 _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XICU is not set\n"); 191 _exit(); 192 #endif 193 } 194 195 //////////////////////////////////////////////////////////////////////////////// 196 // This function returns the address of a WTI mailbox defined by 197 // the "wti_index" argument, in the unsigned int "address" argument. 198 // It is used by the GIET to configurate the IOPIC component. 199 // There is no access to a specific XCU component in a specific cluster. 200 // returns 0 if success, > 0 if error. 201 //////////////////////////////////////////////////////////////////////////////// 202 void _xcu_get_wti_address( unsigned int wti_index, 203 unsigned int * address ) 204 { 205 #if USE_XICU 206 if (wti_index >= 32) _exit(); 207 208 unsigned int xcu_address = (unsigned int)&seg_xcu_base; 209 *address = xcu_address + (XICU_REG(XICU_WTI_REG, wti_index)<<2); 210 211 #else 212 _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XICU is not set\n"); 213 _exit(); 214 #endif 215 } 216 217 //////////////////////////////////////////////////////////////////////////////// 176 218 // This function activates a timer contained in XICU by writing in the 177 219 // proper register the period value. 178 // Returns 0 if success, > 0 if error. 179 //////////////////////////////////////////////////////////////////////////////// 180 unsigned int _xcu_timer_start( unsigned int cluster_xy, 181 unsigned int pti_index, 182 unsigned int period ) 183 { 184 // parameters checking 185 unsigned int x = cluster_xy >> Y_WIDTH; 186 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 187 if (x >= X_SIZE) return 1; 188 if (y >= Y_SIZE) return 1; 189 190 #if USE_XICU 220 //////////////////////////////////////////////////////////////////////////////// 221 void _xcu_timer_start( unsigned int cluster_xy, 222 unsigned int pti_index, 223 unsigned int period ) 224 { 225 #if USE_XICU 226 // parameters checking 227 unsigned int x = cluster_xy >> Y_WIDTH; 228 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 229 if (x >= X_SIZE) _exit(); 230 if (y >= Y_SIZE) _exit(); 231 191 232 volatile unsigned int* xcu_address = 192 233 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 194 235 195 236 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period; 196 return 0; 197 #else 198 _tty_get_lock( 0 ); 199 _puts("[GIET ERROR] _xcu_timer_start should not be used if USE_XICU is not set\n"); 200 _tty_release_lock( 0 ); 201 return 1; 202 #endif 203 } 204 205 ////////////////////////////////////////////////////////////////////////////// 206 // _xcu_timer_stop() 237 238 #else 239 _printf("[GIET ERROR] in _xcu_timer_start() USE_XICU is not set\n"); 240 _exit(); 241 #endif 242 } 243 244 ////////////////////////////////////////////////////////////////////////////// 207 245 // This function desactivates a timer in XICU component 208 246 // by writing in the proper register. 209 // Returns 0 if success, > 0 if error. 210 ////////////////////////////////////////////////////////////////////////////// 211 unsigned int _xcu_timer_stop( unsigned int cluster_xy, 212 unsigned int pti_index) 213 { 214 // parameters checking 215 unsigned int x = cluster_xy >> Y_WIDTH; 216 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 217 if (x >= X_SIZE) return 1; 218 if (y >= Y_SIZE) return 1; 219 220 #if USE_XICU 247 ////////////////////////////////////////////////////////////////////////////// 248 void _xcu_timer_stop( unsigned int cluster_xy, 249 unsigned int pti_index) 250 { 251 #if USE_XICU 252 // parameters checking 253 unsigned int x = cluster_xy >> Y_WIDTH; 254 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 255 if (x >= X_SIZE) _exit(); 256 if (y >= Y_SIZE) _exit(); 257 221 258 volatile unsigned int * xcu_address = 222 259 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 224 261 225 262 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0; 226 return 0; 227 #else 228 _tty_get_lock( 0 ); 229 _puts("[GIET ERROR] _xcu_timer_stop should not be used if USE_XICU is not set\n"); 230 _tty_release_lock( 0 ); 231 return 1; 232 #endif 233 } 234 235 ////////////////////////////////////////////////////////////////////////////// 236 // _xcu_timer_reset_irq() 263 264 #else 265 _printf("[GIET ERROR] in _xcu_timer_stop() USE_XICU is not set\n"); 266 _exit(); 267 #endif 268 } 269 270 ////////////////////////////////////////////////////////////////////////////// 237 271 // This function acknowlegge a timer interrupt in XICU 238 272 // component by reading in the proper register. 239 273 // It can be used by both the isr_switch() for a "system" timer, 240 274 // or by the _isr_timer() for an "user" timer. 241 // Returns 0 if success, > 0 if error. 242 ////////////////////////////////////////////////////////////////////////////// 243 unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 244 unsigned int pti_index ) 245 { 246 // parameters checking 247 unsigned int x = cluster_xy >> Y_WIDTH; 248 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 249 if (x >= X_SIZE) return 1; 250 if (y >= Y_SIZE) return 1; 251 252 #if USE_XICU 275 ////////////////////////////////////////////////////////////////////////////// 276 void _xcu_timer_reset_irq( unsigned int cluster_xy, 277 unsigned int pti_index ) 278 { 279 #if USE_XICU 280 // parameters checking 281 unsigned int x = cluster_xy >> Y_WIDTH; 282 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 283 if (x >= X_SIZE) _exit(); 284 if (y >= Y_SIZE) _exit(); 285 253 286 volatile unsigned int * xcu_address = 254 287 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 256 289 257 290 xcu_address[XICU_REG(XICU_PTI_ACK, pti_index)]; 258 return 0; 259 #else 260 _tty_get_lock( 0 ); 261 _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n"); 262 _tty_release_lock( 0 ); 263 return 1; 264 #endif 265 } 266 267 ////////////////////////////////////////////////////////////////////////////// 268 // _xcu_timer_reset_cpt() 291 292 #else 293 _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XICU is not set\n"); 294 _exit(); 295 #endif 296 } 297 298 ////////////////////////////////////////////////////////////////////////////// 269 299 // This function resets a timer counter. To do so, we re-write the period 270 300 // in the proper register, what causes the count to restart. 271 301 // The period value is read from the same (TIMER_PERIOD) register, 272 302 // this is why in appearance we do nothing useful (read a value 273 // from a register and write this value in the same register) 303 // from a register and write this value in the same register). 274 304 // This function is called during a context switch (user or preemptive) 275 305 ///////////////////////////////////////////////////////////////////////////// 276 unsigned int_xcu_timer_reset_cpt( unsigned int cluster_xy,277 278 { 279 // parameters checking 280 unsigned int x = cluster_xy >> Y_WIDTH;281 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);282 if (x >= X_SIZE) return 1;283 if ( y >= Y_SIZE) return 1;284 285 #if USE_XICU 306 void _xcu_timer_reset_cpt( unsigned int cluster_xy, 307 unsigned int pti_index ) 308 { 309 #if USE_XICU 310 // parameters checking 311 unsigned int x = cluster_xy >> Y_WIDTH; 312 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 313 if (x >= X_SIZE) _exit(); 314 if (y >= Y_SIZE) _exit(); 315 286 316 volatile unsigned int * xcu_address = 287 317 (unsigned int *) ((unsigned int) &seg_xcu_base + … … 294 324 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0; 295 325 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period; 296 return 0; 297 #else 298 _tty_get_lock( 0 ); 299 _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n"); 300 _tty_release_lock( 0 ); 301 return 1; 326 327 #else 328 _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XICU is not set\n"); 329 _exit(); 302 330 #endif 303 331 } -
soft/giet_vm/giet_drivers/xcu_driver.h
r281 r295 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel. 8 // This driver supports the SoCLib vci_xicu, that is a vectorised interrupt 9 // controler supporting IPI (Inter Processor Interrupts) and integrated timers. 10 // 11 // It can exist several interrupt controller unit in the architecture 12 // (one per cluster), and each one can contain several channels. 13 // The number of XICU channels is equal to NB_PROCS_MAX, because there is 14 // one private XICU channel per processor in a cluster. 15 //////////////////////////////////////////////////////////////////////////////// 16 // The virtual base address of the segment associated to the component is: 17 // 18 // seg_xcu_base + cluster_xy * vseg_cluster_increment 19 // 20 // The seg_xcu_base and vseg_cluster_increment values must be defined 21 // in giet_vsegs.ld file. 22 //////////////////////////////////////////////////////////////////////////////// 7 23 8 24 #ifndef _GIET_XCU_DRIVER_H_ … … 44 60 /////////////////////////////////////////////////////////////////////////////////// 45 61 46 extern unsigned int _xcu_get_index( unsigned int cluster_xy, 47 unsigned int irq_index, 48 unsigned int * buffer ); 62 extern void _xcu_set_mask( unsigned int cluster_xy, 63 unsigned int channel, 64 unsigned int mask, 65 unsigned int irq_type ); 49 66 50 extern unsigned int _xcu_set_mask( unsigned int cluster_xy,51 unsigned int irq_index,52 unsigned int mask,53 unsigned int is_timer);67 extern void _xcu_get_index( unsigned int cluster_xy, 68 unsigned int channel, 69 unsigned int * index, 70 unsigned int * irq_type ); 54 71 55 extern unsigned int _xcu_send_ipi( unsigned int cluster_xy,56 57 72 extern void _xcu_send_wti( unsigned int cluster_xy, 73 unsigned int wti_index, 74 unsigned int wdata ); 58 75 59 extern unsigned int _xcu_timer_start( unsigned int cluster_xy,60 unsigned int pti_index,61 unsigned int period );76 extern void _xcu_get_wti_value( unsigned int cluster_xy, 77 unsigned int wti_index, 78 unsigned int * value ); 62 79 63 extern unsigned int _xcu_timer_stop( unsigned int cluster_xy,64 unsigned int pti_index );80 extern void _xcu_get_wti_address( unsigned int wti_index, 81 unsigned int * address ); 65 82 66 extern unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 67 unsigned int pti_index ); 83 extern void _xcu_timer_start( unsigned int cluster_xy, 84 unsigned int pti_index, 85 unsigned int period ); 68 86 69 extern unsigned int _xcu_timer_reset_cpt( unsigned int cluster_xy, 70 unsigned int pti_index ); 87 extern void _xcu_timer_stop( unsigned int cluster_xy, 88 unsigned int pti_index ); 89 90 extern void _xcu_timer_reset_irq( unsigned int cluster_xy, 91 unsigned int pti_index ); 92 93 extern void _xcu_timer_reset_cpt( unsigned int cluster_xy, 94 unsigned int pti_index ); 71 95 72 96 ///////////////////////////////////////////////////////////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.