Changeset 529 for soft/giet_vm/giet_drivers
- Timestamp:
- Mar 27, 2015, 11:51:33 AM (10 years ago)
- Location:
- soft/giet_vm/giet_drivers
- Files:
-
- 2 deleted
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/bdv_driver.c
r496 r529 2 2 // File : bdv_driver.c 3 3 // Date : 23/05/2013 4 // Author : alain greiner 5 // Maintainer: cesar fuguet 4 // Author : alain greiner cesar fuguet 6 5 // Copyright (c) UPMC-LIP6 7 6 /////////////////////////////////////////////////////////////////////////////////// 8 7 // Implementation notes: 9 // 1. In order to share code, the two _bdv_read() and _bdv_write() functions 10 // call the same _bdv_access() function. 11 // 2. All accesses to BDV registers are done by the two 12 // _bdv_set_register() and _bdv_get_register() low-level functions, 13 // that are handling virtual / physical extended addressing. 8 // All accesses to BDV registers are done by the two 9 // _bdv_set_register() and _bdv_get_register() low-level functions, 10 // that are handling virtual / physical extended addressing. 14 11 /////////////////////////////////////////////////////////////////////////////////// 15 12 … … 18 15 #include <bdv_driver.h> 19 16 #include <xcu_driver.h> 20 #include < ioc_driver.h>17 #include <kernel_locks.h> 21 18 #include <utils.h> 22 19 #include <tty0.h> 23 20 #include <ctx_handler.h> 24 25 /////////////////////////////////////////////////////////////////////////////// 26 // BDV global variables 27 /////////////////////////////////////////////////////////////////////////////// 28 21 #include <irq_handler.h> 22 23 /////////////////////////////////////////////////////////////////////////////// 24 // Global variables 25 /////////////////////////////////////////////////////////////////////////////// 26 27 // lock protecting single channel BDV peripheral 29 28 __attribute__((section(".kdata"))) 30 29 spin_lock_t _bdv_lock __attribute__((aligned(64))); 31 30 31 // global index of the waiting task (only used in descheduling mode) 32 __attribute__((section(".kdata"))) 33 unsigned int _bdv_gtid; 34 35 // BDV peripheral status (only used in descheduling mode) 32 36 __attribute__((section(".kdata"))) 33 37 unsigned int _bdv_status; 34 35 __attribute__((section(".kdata")))36 unsigned int _bdv_gtid;37 38 38 39 /////////////////////////////////////////////////////////////////////////////// … … 56 57 57 58 /////////////////////////////////////////////////////////////////////////////// 58 // This function transfer data between a memory buffer and the block device. 59 // The buffer lentgth is (count*block_size) bytes. 60 // Arguments are: 61 // - to_mem : from external storage to memory when non 0. 62 // - mode : BOOT / KERNEL / USER 63 // - lba : first block index on the external storage. 64 // - buf_paddr : physical base address of the memory buffer. 65 // - count : number of blocks to be transfered. 66 // Returns 0 if success, > 0 if error. 67 /////////////////////////////////////////////////////////////////////////////// 68 static unsigned int _bdv_access( unsigned int to_mem, 69 unsigned int mode, 70 unsigned int lba, 71 unsigned long long buf_paddr, 72 unsigned int count) 59 // Extern functions 60 /////////////////////////////////////////////////////////////////////////////// 61 62 ///////////////////////////////////////////////////// 63 unsigned int _bdv_access( unsigned int use_irq, 64 unsigned int to_mem, 65 unsigned int lba, 66 unsigned long long buf_paddr, 67 unsigned int count) 73 68 { 74 69 unsigned int procid = _get_procid(); … … 78 73 79 74 #if GIET_DEBUG_IOC_DRIVER 80 _puts("\n[BDV DEBUG] _bdv_access() : P["); 81 _putd( x ); 82 _puts(","); 83 _putd( y ); 84 _puts(","); 85 _putd( p ); 86 _puts("] enters at cycle "); 87 _putd( _get_proctime() ); 88 _puts("\n - to_mem = "); 89 _putd( to_mem ); 90 _puts("\n - mode = "); 91 _putd( mode ); 92 _puts("\n - paddr = "); 93 _putl( buf_paddr ); 94 _puts("\n - sectors = "); 95 _putd( count ); 96 _puts("\n - lba = "); 97 _putx( lba ); 98 _puts("\n"); 99 #endif 100 101 unsigned int error = 0; 75 _printf("\n[BDV DEBUG] P[%d,%d,%d] enters _bdv_access at cycle %d\n" 76 " use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n", 77 x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count ); 78 #endif 79 80 // check buffer alignment 81 if( buf_paddr & 0x1FF ) 82 { 83 _printf("\n[BDV ERROR] in _bdv_access() : buffer not block aligned\n"); 84 return -1; 85 } 86 87 unsigned int error; 88 unsigned int status; 102 89 103 90 // get the lock protecting BDV 104 91 _spin_lock_acquire( &_bdv_lock ); 105 106 #if GIET_DEBUG_IOC_DRIVER107 _puts("\n[BDV DEBUG] _bdv_access() : P[");108 _putd( x );109 _puts(",");110 _putd( y );111 _puts(",");112 _putd( p );113 _puts("] get _bdv_lock at cycle ");114 _putd( _get_proctime() );115 _puts("\n");116 #endif117 92 118 93 // set device registers … … 122 97 _bdv_set_register( BLOCK_DEVICE_LBA , lba ); 123 98 124 // In BOOT mode, we launch transfer, and poll the BDV_STATUS 125 // register because IRQs are masked. 126 if ( mode == IOC_BOOT_MODE ) 99 ///////////////////////////////////////////////////////////////////// 100 // In synchronous mode, we launch transfer, 101 // and poll the BDV_STATUS register until completion. 102 ///////////////////////////////////////////////////////////////////// 103 if ( use_irq == 0 ) 127 104 { 128 105 // Launch transfert … … 131 108 132 109 #if GIET_DEBUG_IOC_DRIVER 133 _puts("\n[BDV DEBUG] _bdv_access() : P["); 134 _putd( x ); 135 _puts(","); 136 _putd( y ); 137 _puts(","); 138 _putd( p ); 139 _puts("] launch transfer in polling mode at cycle "); 140 _putd( _get_proctime() ); 141 _puts("\n"); 142 #endif 143 unsigned int status; 110 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer" 111 " in polling mode at cycle %d\n", 112 x , y , p , _get_proctime() ); 113 #endif 114 144 115 do 145 116 { … … 147 118 148 119 #if GIET_DEBUG_IOC_DRIVER 149 _puts("\n[BDV DEBUG] _bdv_access() : P["); 150 _putd( x ); 151 _puts(","); 152 _putd( y ); 153 _puts(","); 154 _putd( p ); 155 _puts("] wait on BDV_STATUS register ...\n"); 120 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] wait on BDV_STATUS ...\n", 121 x , y , p ); 156 122 #endif 157 123 } … … 164 130 error = ( (status == BLOCK_DEVICE_READ_ERROR) || 165 131 (status == BLOCK_DEVICE_WRITE_ERROR) ); 166 167 // release lock 168 _spin_lock_release( &_bdv_lock ); 169 } 170 // in USER or KERNEL mode, we deschedule the task. 171 // When the task is rescheduled, we check the _bdv_status variable, 172 // and release the lock. 132 } 133 134 ///////////////////////////////////////////////////////////////// 135 // in descheduling mode, we deschedule the task 136 // and use an interrupt to reschedule the task. 173 137 // We need a critical section, because we must reset the RUN bit 174 // before to launch the transfer, and we don't want to be descheduled 175 // between these two operations. 138 // before to launch the transfer, and we don't want to be 139 // descheduled between these two operations. 140 ///////////////////////////////////////////////////////////////// 176 141 else 177 142 { 178 143 unsigned int save_sr; 144 unsigned int wti_index; 179 145 unsigned int ltid = _get_current_task_id(); 180 146 181 // activates BDV interrupt s147 // activates BDV interrupt 182 148 _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 1 ); 183 149 184 // set the _bdv_status variable185 _bdv_status = BLOCK_DEVICE_BUSY;150 // allocate a WTI mailbox to the calling proc if external IRQ 151 if ( USE_PIC ) _ext_irq_alloc( ISR_BDV , 0 , &wti_index ); 186 152 187 153 // enters critical section … … 197 163 198 164 #if GIET_DEBUG_IOC_DRIVER 199 _puts("\n[BDV DEBUG] _bdv_access() : P["); 200 _putd( x ); 201 _puts(","); 202 _putd( y ); 203 _puts(","); 204 _putd( p ); 205 _puts("] launch transfer in interrupt mode at cycle "); 206 _putd( _get_proctime() ); 207 _puts("\n"); 165 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer" 166 " in descheduling mode at cycle %d\n", 167 x , y , p , _get_proctime() ); 208 168 #endif 209 169 … … 212 172 213 173 #if GIET_DEBUG_IOC_DRIVER 214 _puts("\n[BDV DEBUG] _bdv_access() : P["); 215 _putd( x ); 216 _puts(","); 217 _putd( y ); 218 _puts(","); 219 _putd( p ); 220 _puts("] resume execution after descheduling\n"); 221 #endif 174 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] resume execution at cycle %d\n", 175 x , y , p , _get_proctime() ); 176 #endif 177 178 // release WTI mailbox if external IRQ 179 if ( USE_PIC ) _ext_irq_release( ISR_BDV , 0 , wti_index ); 180 222 181 // restore SR 223 182 _it_restore( &save_sr ); … … 226 185 error = ( (_bdv_status == BLOCK_DEVICE_READ_ERROR) || 227 186 (_bdv_status == BLOCK_DEVICE_WRITE_ERROR) ); 228 229 // reset _bdv_status and release lock 230 _bdv_status = BLOCK_DEVICE_IDLE; 231 _spin_lock_release( &_bdv_lock ); 232 } 233 234 #if GIET_DEBUG_IOC_DRIVER 235 _puts("\n[BDV DEBUG] _bdv_access() : P["); 236 _putd( x ); 237 _puts(","); 238 _putd( y ); 239 _puts(","); 240 _putd( p ); 241 _puts("] exit at cycle "); 242 _putd( _get_proctime() ); 243 _puts(" / error = "); 244 _putd( error ); 245 _puts("\n"); 187 } 188 189 // release lock 190 _spin_lock_release( &_bdv_lock ); 191 192 #if GIET_DEBUG_IOC_DRIVER 193 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] exit at cycle %d\n", 194 x , y , p , _get_proctime() ); 246 195 #endif 247 196 … … 249 198 } // end _bdv_access() 250 199 251 ///////////////////////////////////////////////////////////////////////////////252 // External functions253 ///////////////////////////////////////////////////////////////////////////////254 255 200 //////////////////////// 256 201 unsigned int _bdv_init() … … 264 209 _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 0 ); 265 210 return 0; 266 }267 268 ////////////////////////////////////////////////269 unsigned int _bdv_read( unsigned int mode,270 unsigned int lba,271 unsigned long long buffer,272 unsigned int count)273 {274 return _bdv_access( 1, // read access275 mode,276 lba,277 buffer,278 count );279 }280 281 /////////////////////////////////////////////////282 unsigned int _bdv_write( unsigned int mode,283 unsigned int lba,284 unsigned long long buffer,285 unsigned int count )286 {287 return _bdv_access( 0, // write access288 mode,289 lba,290 buffer,291 count );292 }293 294 //////////////////////////////295 unsigned int _bdv_get_status()296 {297 return _bdv_get_register( BLOCK_DEVICE_STATUS );298 }299 300 //////////////////////////////////301 unsigned int _bdv_get_block_size()302 {303 return _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE );304 211 } 305 212 … … 309 216 unsigned int channel ) // unused 310 217 { 311 // get BDV status (and reset IRQ)218 // get BDV status and reset BDV_IRQ 312 219 unsigned int status = _bdv_get_register( BLOCK_DEVICE_STATUS ); 313 220 … … 316 223 (status == BLOCK_DEVICE_BUSY) ) return; 317 224 318 // save status in kernel buffer _bdv_status319 _bdv_status = status; 225 // register status in global variable 226 _bdv_status = status; 320 227 321 228 // identify task waiting on BDV … … 333 240 ltid, 334 241 CTX_RUN_ID, // CTX_RUN slot 335 1 ); // running 336 337 // requires a context switch for remote processor running the waiting task242 1 ); // running value 243 244 // send a WAKUP WTI to processor running the sleeping task 338 245 _xcu_send_wti( remote_cluster, 339 246 remote_p, 340 0 ); // don't force context switch if not idle341 342 #if GIET_DEBUG_I RQS // we don't take the TTY lock to avoid deadlock247 0 ); // don't force context switch 248 249 #if GIET_DEBUG_IOC_DRIVER 343 250 unsigned int procid = _get_procid(); 344 251 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 345 252 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); 346 253 unsigned int p = procid & ((1<<P_WIDTH)-1); 347 348 _puts("\n[IRQS DEBUG] Processor["); 349 _putd(x ); 350 _puts(","); 351 _putd(y ); 352 _puts(","); 353 _putd(p ); 354 _puts("] enters _bdv_isr() at cycle "); 355 _putd(_get_proctime() ); 356 _puts("\n for task "); 357 _putd(ltid ); 358 _puts(" running on processor["); 359 _putd(remote_x ); 360 _puts(","); 361 _putd(remote_y ); 362 _puts(","); 363 _putd(remote_p ); 364 _puts(" / bdv status = "); 365 _putx(_bdv_status ); 366 _puts("\n"); 367 #endif 368 369 } 254 _printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _bdv_isr() at cycle %d\n" 255 " for task %d running on P[%d,%d,%d] / bdv_status = %x\n", 256 x , y , p , _get_proctime() , 257 ltid , remote_x , remote_y , remote_p , status ); 258 #endif 259 260 } // end bdv_isr() 370 261 371 262 -
soft/giet_vm/giet_drivers/bdv_driver.h
r496 r529 10 10 // a single channel, block oriented, external storage contrÃŽler. 11 11 // 12 // The _bdv_ read() and _bdv_write() functions are always blocking.13 // They can be called in 3modes:12 // The _bdv_access() function supports both read and write access to block device, 13 // and implement two operating modes: 14 14 // 15 // - In BOOT mode, these functions usea polling policy on the BDV STATUS15 // - in "synchronous" mode, it uses a polling policy on the BDV STATUS 16 16 // register to detect transfer completion, as interrupts are not activated. 17 17 // This mode is used by the boot code to load the map.bin file into memory 18 18 // (before MMU activation), or to load the .elf files (after MMU activation). 19 // 20 // - In KERNEL mode, these functions use a descheduling strategy: 21 // The ISR executed when transfer completes should restart the calling task. 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: 26 // The ISR executed when transfer completes should restart the calling task, 27 // The user access right to the memory buffer must be checked. 28 // This mode must be used for a "read/write" system call. 29 // 19 // - In "descheduling" mode, ir uses a descheduling + IRQ policy. 20 // The ISR executed when transfer completes should restart the calling task, 21 // as the calling task global index has been saved in the _bdv_gtid variable. 22 // 30 23 // As the BDV component can be used by several programs running in parallel, 31 // the _bdv_lock variable guaranties exclusive access to the device. The 32 // _bdv_read() and _bdv_write() functions use atomic LL/SC to get the lock. 33 // 34 // Finally, the memory buffer must fulfill the following conditions: 35 // - The buffer must be word aligned, 36 // - The buffer must be mapped in user space for an user access, 37 // - The buffer must be writable in case of (to_mem) access, 38 // - The total number of physical pages occupied by the user buffer cannot 39 // be larger than 512 pages if the IOMMU is activated, 40 // - All physical pages occupied by the user buffer must be contiguous 41 // if the IOMMU is not activated. 42 // An error code is returned if these conditions are not verified. 24 // the _bdv_lock variable guaranties exclusive access to the device. 43 25 // 44 26 // The SEG_IOC_BASE address must be defined in the hard_config.h file. … … 86 68 87 69 /////////////////////////////////////////////////////////////////////////////// 88 // BDV global variables70 // Global variables 89 71 /////////////////////////////////////////////////////////////////////////////// 90 72 91 73 extern spin_lock_t _bdv_lock; 74 75 extern unsigned int _bdv_gtid; 76 92 77 extern unsigned int _bdv_status; 93 extern unsigned int _bdv_gtid;94 78 95 79 /////////////////////////////////////////////////////////////////////////////////// … … 104 88 105 89 /////////////////////////////////////////////////////////////////////////////////// 106 // Transfer data from the block device to a memory buffer. 107 // - mode : BOOT / KERNEL / USER 90 // Transfer data to/from the block device from/to a memory buffer. 91 // - use_irq : descheduling + IRQ if non zero / polling if zero 92 // - to_mem : from external storage to memory when non 0. 108 93 // - lba : first block index on the block device 109 // - buffer : base address of the memory buffer (must be word aligned) 110 // - count : number of blocks to be transfered. 111 // Returns 0 if success, > 0 if error. 112 //////////////////////////////////////////////////////////////////////////////////// 113 extern unsigned int _bdv_read( unsigned int mode, 114 unsigned int lba, 115 unsigned long long buffer, 116 unsigned int count ); 117 118 /////////////////////////////////////////////////////////////////////////////////// 119 // Transfer data from a memory buffer to the block device. 120 // - mode : BOOT / KERNEL / USER 121 // - lba : first block index on the block device 122 // - buffer : base address of the memory buffer (must be word aligned) 94 // - buffer : pbase address of the memory buffer (must be word aligned) 123 95 // - count : number of blocks to be transfered. 124 96 // Returns 0 if success, > 0 if error. 125 97 /////////////////////////////////////////////////////////////////////////////////// 126 extern unsigned int _bdv_write( unsigned int mode, 127 unsigned int lba, 128 unsigned long long buffer, 129 unsigned int count ); 130 131 /////////////////////////////////////////////////////////////////////////////////// 132 // Returns device status. 133 /////////////////////////////////////////////////////////////////////////////////// 134 extern unsigned int _bdv_get_status(); 135 136 /////////////////////////////////////////////////////////////////////////////////// 137 // Returns block size. 138 /////////////////////////////////////////////////////////////////////////////////// 139 extern unsigned int _bdv_get_block_size(); 98 extern unsigned int _bdv_access( unsigned int use_irq, 99 unsigned int to_mem, 100 unsigned int lba, 101 unsigned long long buffer, 102 unsigned int count ); 140 103 141 104 /////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/dma_driver.c
r496 r529 88 88 89 89 //////////////////////////////////////////////// 90 unsigned int _dma_init( unsigned int cluster_xy,91 92 { 93 #if NB_DMA_CHANNELS > 0 94 95 // parameters checking90 void _dma_disable_irq( unsigned int cluster_xy, 91 unsigned int channel_id ) 92 { 93 #if NB_DMA_CHANNELS > 0 94 95 // check DMA channel parameters 96 96 unsigned int x = cluster_xy >> Y_WIDTH; 97 97 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 98 if (x >= X_SIZE) return 1; 99 if (y >= Y_SIZE) return 1; 100 if (channel_id >= NB_DMA_CHANNELS) return 1; 98 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 99 { 100 _puts("\n[DMA ERROR] in _dma_disable_irq() : illegal DMA channel "); 101 _exit(); 102 } 101 103 102 104 // disable interrupt for selected channel 103 105 _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1); 104 return 0; 105 #else 106 return 1; 107 #endif 108 } 109 110 ////////////////////////////////////////////////// 111 unsigned int _dma_reset( unsigned int cluster_xy, 106 107 #endif 108 } 109 110 ///////////////////////////////////////////////// 111 void _dma_reset_channel( unsigned int cluster_xy, 112 112 unsigned int channel_id ) 113 113 { 114 114 #if NB_DMA_CHANNELS > 0 115 115 116 // parameters checking116 // check DMA channel parameters 117 117 unsigned int x = cluster_xy >> Y_WIDTH; 118 118 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 119 if (x >= X_SIZE) return 1; 120 if (y >= Y_SIZE) return 1; 121 if (channel_id >= NB_DMA_CHANNELS) return 1; 119 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 120 { 121 _puts("\n[DMA ERROR] in _dma_reset_channel() : illegal DMA channel "); 122 _exit(); 123 } 122 124 123 125 // reset selected channel 124 126 _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0); 125 return 0; 126 #else 127 return 1; 128 #endif 129 } 130 131 ////////////////////////////////////////////////////// 132 unsigned int _dma_get_status( unsigned int cluster_xy, 133 unsigned int channel_id ) 134 { 135 #if NB_DMA_CHANNELS > 0 136 137 // parameters checking 127 128 #endif 129 } 130 131 /////////////////////////////////////////////////////// 132 void _dma_get_status( unsigned int cluster_xy, 133 unsigned int channel_id, 134 unsigned int* status ) 135 { 136 #if NB_DMA_CHANNELS > 0 137 138 // check DMA channel parameters 138 139 unsigned int x = cluster_xy >> Y_WIDTH; 139 140 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 140 if (x >= X_SIZE) return 1; 141 if (y >= Y_SIZE) return 1; 142 if (channel_id >= NB_DMA_CHANNELS) return 1; 143 144 // get selected channel status 145 return _dma_get_register(cluster_xy, channel_id, DMA_LEN); 146 #else 147 return DMA_IDLE; 141 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 142 { 143 _puts("\n[DMA ERROR] in _dma_get_status() : illegal DMA channel "); 144 _exit(); 145 } 146 147 // returns selected channel status 148 *status = _dma_get_register(cluster_xy, channel_id, DMA_LEN); 149 148 150 #endif 149 151 } … … 157 159 { 158 160 #if NB_DMA_CHANNELS > 0 161 162 // check DMA channel parameters 163 unsigned int x = cluster_xy >> Y_WIDTH; 164 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 165 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 166 { 167 _puts("\n[DMA ERROR] in _dma_start_transfer() : illegal DMA channel "); 168 _exit(); 169 } 159 170 160 171 // selected channel configuration and lauching … … 169 180 _dma_set_register(cluster_xy, channel_id, DMA_LEN, 170 181 (unsigned int)size); 171 172 182 #endif 173 183 } … … 176 186 void _dma_physical_copy( unsigned int cluster_xy, // DMA cluster 177 187 unsigned int channel_id, // DMA channel 178 unsigned long long dst_paddr, // dest inationphysical address179 unsigned long long src_paddr, // s ourcephysical address188 unsigned long long dst_paddr, // dest physical address 189 unsigned long long src_paddr, // src physical address 180 190 unsigned int size ) // bytes 181 191 { 182 192 #if NB_DMA_CHANNELS > 0 183 184 // check DMA channel parameters185 unsigned int x = cluster_xy >> Y_WIDTH;186 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);187 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )188 {189 _puts("\n[DMA ERROR] in _dma_physical_copy() : illegal DMA channel ");190 _exit();191 }192 193 193 194 // check buffers alignment constraints … … 199 200 200 201 #if GIET_DEBUG_DMA_DRIVER 202 unsigned int x = cluster_xy >> Y_WIDTH; 203 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 201 204 _puts("\n[DMA DEBUG] enter _dma_physical_copy() for channel["); 202 205 _putd( x ); … … 212 215 _putl( dst_paddr ); 213 216 _puts("\n - bytes = "); 214 _putd( size ); 215 _puts("\n"); 216 #endif 217 218 // dma channel configuration & lauching 217 _putx( size ); 218 _puts("\n"); 219 #endif 220 221 // dma channel configuration 222 _dma_disable_irq( cluster_xy, channel_id ); 223 224 // dma transfer lauching 219 225 _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 220 226 221 227 // scan dma channel status 222 unsigned int status = _dma_get_status( cluster_xy, channel_id ); 228 unsigned int status; 229 do 230 { 231 _dma_get_status( cluster_xy, channel_id , &status ); 232 233 #if GIET_DEBUG_DMA_DRIVER 234 _puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n"); 235 #endif 236 237 } 223 238 while( (status != DMA_SUCCESS) && 224 239 (status != DMA_READ_ERROR) && 225 (status != DMA_WRITE_ERROR) ) 226 { 227 status = _dma_get_status( cluster_xy, channel_id ); 228 229 #if GIET_DEBUG_DMA_DRIVER 230 _puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n"); 231 #endif 232 233 } 240 (status != DMA_WRITE_ERROR) ); 234 241 235 242 // analyse status 236 243 if( status != DMA_SUCCESS ) 237 244 { 238 _puts("\n[DMA ERROR] in _dma_physical_copy() : bad DMA_STATUS");245 _puts("\n[DMA ERROR] in _dma_physical_copy() : ERROR_STATUS"); 239 246 _exit(); 240 247 } 241 248 242 249 // reset dma channel 243 _dma_reset ( cluster_xy, channel_id );250 _dma_reset_channel( cluster_xy , channel_id ); 244 251 245 252 #if GIET_DEBUG_DMA_DRIVER … … 261 268 void _dma_copy( unsigned int cluster_xy, // DMA cluster 262 269 unsigned int channel_id, // DMA channel 263 unsigned int vspace_id, // vspace index for v2p translation264 270 unsigned int dst_vaddr, // dst_vaddr buffer vbase 265 271 unsigned int src_vaddr, // src_vaddr buffer vbase … … 268 274 #if NB_DMA_CHANNELS > 0 269 275 270 // check DMA channel parameters271 unsigned int x = cluster_xy >> Y_WIDTH;272 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);273 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )274 {275 _puts("\n[DMA ERROR] in _dma_copy() : illegal DMA channel ");276 _exit();277 }278 279 276 // check buffers alignment constraints 280 277 if ( (dst_vaddr & 0x3) || (src_vaddr & 0x3) || (size & 0x3) ) … … 284 281 } 285 282 286 unsigned int ppn; 283 unsigned long long src_paddr; 284 unsigned long long dst_paddr; 287 285 unsigned int flags; 288 286 289 287 #if GIET_DEBUG_DMA_DRIVER 288 unsigned int x = cluster_xy >> Y_WIDTH; 289 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 290 290 _puts("\n[DMA DEBUG] enter _dma_copy() for channel["); 291 291 _putd( x ); … … 305 305 #endif 306 306 307 // checking alignment constraints308 if ( (((unsigned int)dst_vaddr) & 0x3) ||309 (((unsigned int)src_vaddr) & 0x3) ||310 (size & 0x3) )311 {312 _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");313 _exit();314 }315 316 // get vspace page table pointer317 unsigned int pt = _ptabs_vaddr[vspace_id];318 319 307 // get src_paddr buffer physical addresse 320 _v2p_translate( (page_table_t*)pt, // page table pointer 321 src_vaddr>>12, // vpn 322 &ppn, // ppn 323 &flags ); // flags 324 unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 325 (unsigned long long)(src_vaddr & 0x00000FFF); 308 src_paddr = _v2p_translate( src_vaddr , &flags ); 326 309 327 310 // get dst_paddr buffer physical addresse 328 _v2p_translate( (page_table_t*)pt, // page table pointer 329 dst_vaddr>>12, // vpn 330 &ppn, // ppn 331 &flags ); // flags 332 unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 333 (unsigned long long)(dst_vaddr & 0x00000FFF); 311 dst_paddr = _v2p_translate( dst_vaddr , &flags ); 334 312 335 313 #if GIET_DEBUG_DMA_DRIVER … … 345 323 346 324 // scan dma channel status 347 unsigned int status = _dma_get_status( cluster_xy, channel_id ); 325 unsigned int status; 326 do 327 { 328 _dma_get_status( cluster_xy, channel_id , &status ); 329 330 #if GIET_DEBUG_DMA_DRIVER 331 _puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n"); 332 #endif 333 334 } 348 335 while( (status != DMA_SUCCESS) && 349 336 (status != DMA_READ_ERROR) && 350 (status != DMA_WRITE_ERROR) ) 351 { 352 status = _dma_get_status( cluster_xy, channel_id ); 353 354 #if GIET_DEBUG_DMA_DRIVER 355 _puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n"); 356 #endif 357 358 } 337 (status != DMA_WRITE_ERROR) ); 359 338 360 339 // analyse status … … 365 344 } 366 345 // reset dma channel 367 _dma_reset ( cluster_xy, channel_id );346 _dma_reset_channel( cluster_xy, channel_id ); 368 347 369 348 #if GIET_DEBUG_DMA_DRIVER … … 380 359 #endif 381 360 } // end _dma_copy 361 382 362 383 363 ///////////////////////////////////// -
soft/giet_vm/giet_drivers/dma_driver.h
r518 r529 15 15 // 16 16 // A DMA channel is a private ressource allocated to a given processor. 17 // It is exclusively used by the kerne tto speedup data transfers, and17 // It is exclusively used by the kernel to speedup data transfers, and 18 18 // there is no lock protecting exclusive access to the channel. 19 19 // As the kernel uses a polling policy on the DMA_STATUS register to detect … … 23 23 // SEG_DMA_BASE + cluster_xy * PERI_CLUSTER_INCREMENT + DMA_SPAN * channel_id 24 24 // 25 // The SEG_DMA_BASE virtual address mus be defined in the hard_config.h file.25 // The SEG_DMA_BASE virtual address must be defined in the hard_config.h file. 26 26 ////////////////////////////////////////////////////////////////////////////////// 27 27 … … 63 63 ////////////////////////////////////////////////////////////////////////////////// 64 64 // This function disables interrupts for one DMA channel in one cluster. 65 // AS the GIET-VM uses a polling policy to detect DMA transfer completion, 66 // the DMA component initialisation must disable interrupts. 67 // Returns 0 if success, returns > 0 if error. 65 // In case of error (illegal DMA channel), an error 66 // message is displayed on TTY0, and system crash. 68 67 ////////////////////////////////////////////////////////////////////////////////// 69 extern unsigned int _dma_init( unsigned int cluster_xy,70 68 extern void _dma_disable_irq( unsigned int cluster_xy, 69 unsigned int channel_id ); 71 70 72 71 ////////////////////////////////////////////////////////////////////////////////// 73 72 // This function re-initialises one DMA channel in one cluster after transfer 74 73 // completion. It actually forces the channel to return in IDLE state. 74 // In case of error (illegal DMA channel), an error 75 // message is displayed on TTY0, and system crash. 75 76 ////////////////////////////////////////////////////////////////////////////////// 76 extern unsigned int _dma_reset( unsigned int cluster_xy,77 extern void _dma_reset_channel( unsigned int cluster_xy, 77 78 unsigned int channel_id ); 78 79 79 80 ////////////////////////////////////////////////////////////////////////////////// 80 // This function returns the status of a DMA channel in a given cluster 81 // This function returns the status of a DMA channel in a given cluster. 82 // In case of error (illegal DMA channel), an error 83 // message is displayed on TTY0, and system crash. 81 84 ////////////////////////////////////////////////////////////////////////////////// 82 extern unsigned int _dma_get_status( unsigned int cluster_xy, 83 unsigned int channel_id ); 85 extern void _dma_get_status( unsigned int cluster_xy, 86 unsigned int channel_id, 87 unsigned int* status ); 84 88 85 89 ////////////////////////////////////////////////////////////////////////////////// … … 87 91 // for the source and destination buffers in a DMA channel in a given cluster 88 92 // and sets the transfer size to lauch the transfer. 93 // In case of error (illegal DMA channel), an error 94 // message is displayed on TTY0, and system crash. 89 95 ////////////////////////////////////////////////////////////////////////////////// 90 96 extern void _dma_start_transfer( unsigned int cluster_xy, … … 118 124 // This function copies a source memory buffer to a destination memory buffer, 119 125 // making virtual to physical address translation: the MMU should be activated. 120 // This blocking function is supposed to be used by the kernel only,121 // and uses a polling policy on DMA_STATUS register to detect completion.122 // Therefore, the DMA_IRQ is NOT used.123 126 // The source and destination buffers base addresses must be word aligned, 124 127 // and the buffer's size must be multiple of 4. … … 128 131 extern void _dma_copy( unsigned int cluster_xy, 129 132 unsigned int channel_id, 130 unsigned int vspace_id,131 133 unsigned int dst_vaddr, 132 134 unsigned int src_vaddr, … … 134 136 135 137 ////////////////////////////////////////////////////////////////////////////////// 136 // This ISR should not be used by the GIET_VM, because the DMA is only 137 // used by the kernel in the boot phase, with a polling strategy. 138 // Interrupt Service Routine. 138 139 ////////////////////////////////////////////////////////////////////////////////// 139 140 extern void _dma_isr( unsigned int irq_type, -
soft/giet_vm/giet_drivers/hba_driver.c
r481 r529 1 ////////////////////////////////////////////////////////////////////////////////// /1 ////////////////////////////////////////////////////////////////////////////////// 2 2 // File : hba_driver.c 3 3 // Date : 23/11/2013 … … 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 7 // Implementation notes: 8 // 1. In order to share code, the two _hba_read() and _hba_write() functions 9 // call the same _hba_set_cmd() function. 10 // 2. All accesses to HBA registers are done by the two 11 // _hba_set_register() and _hba_get_register() low-level functions, 12 // that are handling virtual / physical extended addressing. 8 // All accesses to HBA registers are done by the two 9 // _hba_set_register() and _hba_get_register() low-level functions, 10 // that are handling virtual / physical extended addressing. 13 11 /////////////////////////////////////////////////////////////////////////////////// 14 12 15 13 #include <giet_config.h> 16 #include <ioc_driver.h> 14 #include <hard_config.h> 15 #include <hba_driver.h> 16 #include <xcu_driver.h> 17 #include <kernel_locks.h> 17 18 #include <utils.h> 18 19 #include <tty0.h> 19 #include <iob_driver.h>20 20 #include <ctx_handler.h> 21 #include <mmc_driver.h> 22 #include <hba_driver.h> 21 #include <irq_handler.h> 23 22 #include <vmem.h> 24 23 25 #if !defined( NB_IOC_CHANNELS ) 26 # error: You must define NB_IOC_CHANNELS in the hard_config.h file 27 #endif 28 29 #if ( NB_IOC_CHANNELS > 8 ) 30 # error: NB_IOC_CHANNELS cannot be larger than 8 31 #endif 32 33 #define in_unckdata __attribute__((section (".unckdata"))) 34 35 ////////////////////////////////////////////////////////////////// 24 /////////////////////////////////////////////////////////////////////////////////// 36 25 // Global variables 37 ////////////////////////////////////////////////////////////////// 38 39 // command list array (one per channel) 40 hba_cmd_list_t hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000))); 41 42 // command tables array (32 command tables per channel) 43 hba_cmd_table_t hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000))); 44 45 // command list physical addresses array (one per channel) 46 paddr_t hba_cmd_list_paddr[NB_IOC_CHANNELS]; 47 48 // command tables physical addresses array (32 command tables per channel) 49 paddr_t hba_cmd_table_paddr[NB_IOC_CHANNELS][32]; 50 51 // command list pointer array (one per channel) 52 unsigned int hba_cmd_slot[NB_IOC_CHANNELS]; 26 /////////////////////////////////////////////////////////////////////////////////// 27 28 // global index ot the task, for each entry in the command list 29 __attribute__((section(".kdata"))) 30 unsigned int _hba_gtid[32]; 31 32 // status of the command, for each entry in the command list 33 __attribute__((section(".kdata"))) 34 unsigned int _hba_status[32]; 35 36 // command list : up to 32 commands 37 __attribute__((section(".kdata"))) 38 hba_cmd_desc_t _hba_cmd_list[32] __attribute__((aligned(0x1000))); 39 40 // command tables array : one command table per entry in command list 41 __attribute__((section(".kdata"))) 42 hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x1000))); 43 44 // command list write index : next slot to register a command 45 __attribute__((section(".kdata"))) 46 unsigned int _hba_cmd_ptw; 47 48 // command list read index : next slot to poll a completed command 49 __attribute__((section(".kdata"))) 50 unsigned int _hba_cmd_ptr; 53 51 54 52 ////////////////////////////////////////////////////////////////////////////// 55 // This low level function returns the value of register ( channel /index)53 // This low level function returns the value of register (index) 56 54 ////////////////////////////////////////////////////////////////////////////// 57 unsigned int _hba_get_register( unsigned int channel, 58 unsigned int index ) 59 { 60 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN + index; 55 unsigned int _hba_get_register( unsigned int index ) 56 { 57 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index; 61 58 return _io_extended_read( vaddr ); 62 59 } 63 60 64 61 ////////////////////////////////////////////////////////////////////////////// 65 // This low level function set a new value in register ( channel /index)62 // This low level function set a new value in register (index) 66 63 ////////////////////////////////////////////////////////////////////////////// 67 void _hba_set_register( unsigned int channel, 68 unsigned int index, 64 void _hba_set_register( unsigned int index, 69 65 unsigned int value ) 70 66 { 71 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN +index;67 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index; 72 68 _io_extended_write( vaddr, value ); 73 69 } 74 70 71 /////////////////////////////////////////////////////////////////////////////// 72 // Extern functions 73 /////////////////////////////////////////////////////////////////////////////// 75 74 76 75 /////////////////////////////////////////////////////////////////////////////// 77 76 // This function register a command in both the command list 78 77 // and the command table, and updates the HBA_PXCI register. 79 // It uses the AHCI Scatter/Gather mechanisme to split the user80 // buffer in several physical buffers, with the constraint that each physical81 // buffer must be an integer number of blocks entirely contained in a single82 // page frame.83 78 // return 0 if success, -1 if error 84 79 /////////////////////////////////////////////////////////////////////////////// 85 unsigned int _hba_cmd_set( unsigned int channel, // channel index 86 unsigned int is_read, // to memory 87 unsigned int lba, // logic block address 88 paddr_t buffer, // buffer physical address 89 unsigned int count ) // number of blocks 90 { 91 unsigned int block_size; // defined by the block device (bytes) 92 unsigned int pxci; // command list status 93 unsigned int cmd_id; // command index in command list 94 80 unsigned int _hba_access( unsigned int use_irq, 81 unsigned int to_mem, 82 unsigned int lba, 83 unsigned long long buf_paddr, 84 unsigned int count ) 85 { 86 unsigned int procid = _get_procid(); 87 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 88 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1); 89 unsigned int p = procid & ((1<<P_WIDTH)-1); 90 91 #if GIET_DEBUG_IOC_DRIVER 92 _printf("\n[HBA DEBUG] P[%d,%d,%d] enters _hba_access at cycle %d\n" 93 " use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n", 94 x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count ); 95 #endif 96 97 unsigned int pxci; // HBA_PXCI register value 98 unsigned int ptw; // command list write pointer 99 unsigned int pxis; // HBA_PXIS register value 95 100 hba_cmd_desc_t* cmd_desc; // command descriptor pointer 96 101 hba_cmd_table_t* cmd_table; // command table pointer 97 102 98 block_size = _hba_get_block_size();99 100 103 // check buffer alignment 101 if( buf fer & (block_size-1))102 { 103 _p uts("\n[GIET ERROR] in _hba_set_cmd() : userbuffer not block aligned\n");104 if( buf_paddr & 0x1FF ) 105 { 106 _printf("\n[HBA ERROR] in _hba_access() : buffer not block aligned\n"); 104 107 return -1; 105 108 } 106 109 107 // get command list status from PXCI register 108 pxci = _hba_get_register( channel, HBA_PXCI ); 109 110 // get command index and return error if command list full 111 cmd_id = hba_cmd_slot[channel]; 112 if( pxci & (1<<cmd_id ) ) 113 { 114 _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel "); 115 _putd( channel ); 116 _puts("\n"); 117 return -1; 118 } 119 110 // get pointer on the next possible entry in command list 111 ptw = _atomic_increment( &_hba_cmd_ptw , 1 ); 112 113 // poll PXCI register until pointed entry empty 114 do 115 { 116 // get PXCI register 117 pxci = _hba_get_register( HBA_PXCI ); 118 } 119 while ( pxci & (1<<ptw) ); 120 120 121 // compute pointers on command descriptor and command table 121 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id]));122 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id]));122 cmd_desc = &_hba_cmd_list[ptw]; 123 cmd_table = &_hba_cmd_table[ptw]; 123 124 124 125 // set buffer descriptor in command table 125 cmd_table->entry[0].dba = (unsigned int)(buf fer);126 cmd_table->entry[0].dbau = (unsigned int)(buf fer >> 32);127 cmd_table->entry[0].dbc = count * block_size;126 cmd_table->entry[0].dba = (unsigned int)(buf_paddr); 127 cmd_table->entry[0].dbau = (unsigned int)(buf_paddr >> 32); 128 cmd_table->entry[0].dbc = count * 512; 128 129 129 130 // initialize command table header … … 138 139 cmd_desc->prdtl[0] = 1; 139 140 cmd_desc->prdtl[1] = 0; 140 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]); 141 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32); 142 if( is_read ) cmd_desc->flag[0] = 0x00; 143 else cmd_desc->flag[0] = 0x40; 141 if( to_mem ) cmd_desc->flag[0] = 0x00; 142 else cmd_desc->flag[0] = 0x40; 144 143 145 // update PXCI register 146 _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) ); 147 148 // update command pointer 149 hba_cmd_slot[channel] = (cmd_id + 1)%32; 150 151 return 0; 152 } 153 154 /* This can be used for a future use with buffer in virtual space 155 156 // get user space page table virtual address 157 user_pt_vbase = _get_context_slot(CTX_PTAB_ID); 158 vpn_min = buf_vaddr >> 12; 159 vpn_max = (buf_vaddr + (block_size*count) - 1) >> 12; 160 offset = buf_vaddr & 0xFFF; 161 offset_last = (buf_vaddr + (block_size*count) - 1) & 0xFFF; 162 163 // initialize all buffer descriptors in command table 164 // (loop on all virtual pages covering the user buffer) 165 for( vpn = vpn_min, buf_id = 0 ; vpn <= vpn_max ; vpn++ ) 166 { 167 paddr_t paddr; 168 unsigned int count; 169 unsigned int ppn; 170 unsigned int flags; 171 unsigned int ko; 172 unsigned int buf_id = 0; 173 174 // get ppn and flags 175 _v2p_translate( (page_table_t*)user_pt_vbase, 176 vpn, 177 &ppn, 178 &flags ); 179 180 // check access rights 181 if ((flags & PTE_U) == 0) 144 // set command in PXCI[ptw] 145 _hba_set_register( HBA_PXCI, pxci + (1<<ptw) ); 146 147 148 ///////////////////////////////////////////////////////////////////// 149 // In synchronous mode, we poll the PXCI register until completion 150 ///////////////////////////////////////////////////////////////////// 151 if ( use_irq == 0 ) 152 { 153 154 #if GIET_DEBUG_IOC_DRIVER 155 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer" 156 " in polling mode at cycle %d\n", 157 x , y , p , _get_proctime() ); 158 #endif 159 // disable IRQs in PXIE register 160 _hba_set_register( HBA_PXIE , 0 ); 161 162 // poll PXCI[ptw] until command completed by HBA 163 do 182 164 { 183 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 184 return -1; 165 pxci = _hba_get_register( HBA_PXCI ) & (1<<ptw); 166 167 #if GIET_DEBUG_IOC_DRIVER 168 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] wait on HBA_STATUS ...\n", 169 x , y , p ); 170 #endif 185 171 } 186 if (((flags & PTE_W) == 0 ) && (is_read == 0) ) 172 while( pxci & (1<<ptw) ); 173 174 // get PXIS register 175 pxis = _hba_get_register( HBA_PXIS ); 176 177 // reset PXIS register 178 _hba_set_register( HBA_PXIS , 0 ); 179 } 180 181 ///////////////////////////////////////////////////////////////// 182 // in descheduling mode, we deschedule the task 183 // and use an interrupt to reschedule the task. 184 // We need a critical section, because we must reset the RUN bit 185 // before to launch the transfer, and we don't want to be 186 // descheduled between these two operations. 187 ///////////////////////////////////////////////////////////////// 188 else 189 { 190 191 #if GIET_DEBUG_IOC_DRIVER 192 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer" 193 " in descheduling mode at cycle %d\n", 194 x , y , p , _get_proctime() ); 195 #endif 196 unsigned int save_sr; 197 unsigned int ltid = _get_current_task_id(); 198 199 // activates HBA interrupts 200 _hba_set_register( HBA_PXIE , 0x00000001 ); 201 202 // set _hba_gtid[ptw] 203 _hba_gtid[ptw] = (procid<<16) + ltid; 204 205 // enters critical section 206 _it_disable( &save_sr ); 207 208 // reset runnable 209 _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 210 211 // deschedule task 212 _ctx_switch(); 213 214 #if GIET_DEBUG_IOC_DRIVER 215 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] resume execution at cycle %d\n", 216 x , y , p , _get_proctime() ); 217 #endif 218 219 // restore SR 220 _it_restore( &save_sr ); 221 222 // get command status 223 pxis = _hba_status[ptw]; 224 } 225 226 #if GIET_DEBUG_IOC_DRIVER 227 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] exit at cycle %d\n", 228 x , y , p , _get_proctime() ); 229 #endif 230 231 if ( pxis & 0x40000000 ) return pxis; 232 else return 0; 233 234 } // end _hba_access() 235 236 237 //////////////////////// 238 unsigned int _hba_init() 239 { 240 unsigned int flags; 241 unsigned int vaddr; 242 unsigned long long paddr; 243 unsigned int c; 244 unsigned int pxclb; 245 unsigned int pxclbu; 246 247 // command list pointers 248 _hba_cmd_ptw = 0; 249 _hba_cmd_ptr = 0; 250 251 // Command list physical addresse 252 vaddr = (unsigned int)(_hba_cmd_list); 253 paddr = _v2p_translate( vaddr , &flags ); 254 pxclb = (unsigned int)paddr; 255 pxclbu = (unsigned int)(paddr>>32); 256 257 // Command tables physical addresses 258 for( c=0 ; c<32 ; c++ ) 259 { 260 // compute command table physical address 261 // for one entry in the command list 262 vaddr = (unsigned int)(&_hba_cmd_table[c]); 263 paddr = _v2p_translate( vaddr , &flags ); 264 265 // initialise the corresponding command descriptor 266 _hba_cmd_list[c].ctba = (unsigned int)paddr; 267 _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32); 268 } 269 270 // set HBA registers 271 _hba_set_register( HBA_PXCLB , pxclb ); 272 _hba_set_register( HBA_PXCLBU, pxclbu ); 273 _hba_set_register( HBA_PXIE , 0 ); 274 _hba_set_register( HBA_PXIS , 0 ); 275 _hba_set_register( HBA_PXCI , 0 ); 276 _hba_set_register( HBA_PXCMD , 1 ); 277 278 return 0; 279 } 280 281 282 ///////////////////////////////////// 283 void _hba_isr( unsigned int irq_type, // HWI / WTI 284 unsigned int irq_id, // index returned by ICU 285 unsigned int channel ) // unused 286 { 287 // get HBA_PXCI containing commands status 288 unsigned int pxci = _hba_get_register( HBA_PXCI ); 289 290 // scan active commands from (_hba_cmd_ptr) to (_hba_cmd_ptw-1) 291 unsigned int c; 292 for ( c = _hba_cmd_ptr ; 293 c != _hba_cmd_ptw ; 294 c = (c + 1) % 32 ) 295 { 296 if ( (pxci & (1<<c)) == 0 ) // command completed 187 297 { 188 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 189 return -1; 298 // increment read pointer; 299 _hba_cmd_ptr++; 300 301 // save PXIS register 302 _hba_status[c] = _hba_get_register( HBA_PXIS ); 303 304 // reset PXIS register 305 _hba_set_register( HBA_PXIS , 0 ); 306 307 // identify waiting task 308 unsigned int remote_procid = _hba_gtid[c]>>16; 309 unsigned int ltid = _hba_gtid[c] & 0xFFFF; 310 unsigned int remote_cluster = remote_procid >> P_WIDTH; 311 unsigned int remote_x = remote_cluster >> Y_WIDTH; 312 unsigned int remote_y = remote_cluster & ((1<<Y_WIDTH)-1); 313 unsigned int remote_p = remote_procid & ((1<<P_WIDTH)-1); 314 315 // re-activates waiting task 316 _set_task_slot( remote_x, 317 remote_y, 318 remote_p, 319 ltid, 320 CTX_RUN_ID, 321 1 ); 322 323 // send a WAKUP WTI to processor running the waiting task 324 _xcu_send_wti( remote_cluster , 325 remote_p , 326 0 ); // don't force context switch 327 328 #if GIET_DEBUG_IOC_DRIVER 329 unsigned int procid = _get_procid(); 330 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 331 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); 332 unsigned int p = procid & ((1<<P_WIDTH)-1); 333 _printf("\n[HBA DEBUG] Processor[%d,%d,%d] executes _hba_isr() :\n" 334 " resume task %d running on P[%d,%d,%d] / status = %x at cyle %d\n", 335 x , y , p , 336 ltid , remote_x , remote_y , remote_p , _hba_status[c] , _get_proctime() ); 337 #endif 190 338 } 191 192 // check buffer index overflow 193 if( buf_id > 245 ) 339 else // command non completed 194 340 { 195 _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 196 return -1; 197 } 198 199 // buffer allocation 200 if( vpn == vpn_min ) // first page: one single buffer 201 { 202 paddr = (((paddr_t)ppn) << 12) + offset; 203 count = 0x1000 - offset; 204 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 205 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 206 cmd_table->entry[buf_id].dbc = count; 207 208 buf_id++; 209 } 210 else if( vpn == vpn_max ) // last page: one single buffer 211 { 212 paddr = (((paddr_t)ppn) << 12); 213 count = offset_last; 214 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 215 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 216 cmd_table->entry[buf_id].dbc = count; 217 218 buf_id++; 219 } 220 else if( offset ) // midle page and offset != 0: two buffers 221 { 222 paddr = (((paddr_t)ppn) << 12); 223 224 count = offset; 225 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 226 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 227 cmd_table->entry[buf_id].dbc = count; 228 229 buf_id++; 230 231 paddr = (((paddr_t)ppn) << 12) + offset; 232 count = 0x1000 - offset; 233 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 234 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 235 cmd_table->entry[buf_id].dbc = count; 236 237 buf_id++; 238 } 239 else // middle page and offset == 0: one buffer 240 { 241 paddr = (((paddr_t)ppn) << 12); 242 count = 0x1000; 243 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 244 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 245 cmd_table->entry[buf_id].dbc = count; 246 247 buf_id++; 341 break; 248 342 } 249 343 } 250 */ 251 252 253 ////////////////////////////////////////////// 254 unsigned int _hba_init( unsigned int channel ) 255 { 256 unsigned int ppn; 257 unsigned int flags; 258 unsigned int vbase; 259 unsigned int c; // c == command index 260 261 // get page_table pointer 262 unsigned int pt = _get_context_slot(CTX_PTAB_ID); 263 264 // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG) 265 _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] ); 266 _hba_set_register( channel, HBA_PXCLBU, 0 ); 267 _hba_set_register( channel, HBA_PXIE , 0x40000001 ); 268 _hba_set_register( channel, HBA_PXIS , 0 ); 269 _hba_set_register( channel, HBA_PXCI , 0 ); 270 _hba_set_register( channel, HBA_PXCMD , 1 ); 271 272 // command list pointer 273 hba_cmd_slot[channel] = 0; 274 275 // Command list physical addresse 276 vbase = (unsigned int)(&hba_cmd_list[channel]); 277 _v2p_translate( (page_table_t*)pt, 278 vbase>>12, 279 &ppn, 280 &flags ); 281 hba_cmd_list_paddr[channel] = ((paddr_t)ppn) | (vbase & 0xFFF); 282 283 // Command tables physical addresses 284 for( c=0 ; c<32 ; c++ ) 285 { 286 vbase = (unsigned int)(&hba_cmd_table[channel][c]); 287 _v2p_translate( (page_table_t*)pt, 288 vbase>>12, 289 &ppn, 290 &flags ); 291 hba_cmd_table_paddr[channel][c] = ((paddr_t)ppn) | (vbase & 0xFFF); 292 } 293 294 return 0; 295 } 296 297 /////////////////////////////////////////////// 298 unsigned int _hba_write( unsigned int channel, 299 unsigned int mode, 300 unsigned int lba, 301 paddr_t buffer, 302 unsigned int count ) 303 { 304 return _hba_cmd_set( channel, 305 0, // write 306 lba, 307 buffer, 308 count ); 309 } 310 311 ////////////////////////////////////////////// 312 unsigned int _hba_read( unsigned int channel, 313 unsigned int mode, 314 unsigned int lba, 315 paddr_t buffer, 316 unsigned int count ) 317 { 318 return _hba_cmd_set( channel, 319 1, // read 320 lba, 321 buffer, 322 count ); 323 } 324 325 ////////////////////////////////// 326 unsigned int _hba_get_block_size() 327 { 328 // TODO The block size must be obtained from the hardware... 329 return 512; 330 } 331 332 //////////////////////////////////////////////////// 333 unsigned int _hba_get_status( unsigned int channel ) 334 { 335 336 if( channel >= NB_IOC_CHANNELS ) 337 { 338 _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 339 _exit(); 340 } 341 342 // get HBA_PXIS value 343 unsigned int status = _hba_get_register( channel, HBA_PXIS ); 344 345 // reset HBA_PXIS 346 _hba_set_register( channel, HBA_PXIS, 0 ); 347 348 return status; 349 } 344 } // end _hba_isr() 350 345 351 346 // Local Variables: -
soft/giet_vm/giet_drivers/hba_driver.h
r437 r529 8 8 // This driver supports the SocLib VciMultiAhci component, that is a multi-channels, 9 9 // block oriented, external storage contrÃŽler, respecting the AHCI standard. 10 // 11 // 1. Each HBA channel define an independant physical disk, but this driver 12 // supports only channel 0, because the GIET-VM uses only one physical disk. 13 // 14 // 2. The "command list" can contain up to 32 independant commands, posted 15 // by different user tasks. These independant transfers are handled 16 // by the HBA device in the same order as they have been written by the 17 // driver(s) in the command list. There is no global lock protecting the 18 // the HBA device, but the command list being a shared structure, the driver 19 // must use an atomic_increment() to get a slot in the command list, 20 // and increment the write pointer. 21 // 22 // 3. This driver implements two operating mode: 23 // - In synchronous mode, the calling task poll the HBA_PXCI register to 24 // detect the command completion (busy waiting). 25 // - In descheduling mode, the calling task is descheduled, and must be 26 // restart when the command is completed. 27 // 28 // 4. As several user tasks can concurrently register commands in the command 29 // list, and there is only one HBA interrupt, this interrupt is not linked 30 // to a specific task. In descheduling mode, the HBA IRQ is a "global" IRQ 31 // that is statically routed to processor P[x_io,y_io,0] in cluster_io. 32 // The associated global HBA_ISR send a WAKUP WTI to all tasks that have 33 // a completed command. This HBA_ISR uses a read pointer on the command 34 // to identify the first expected command completion. The incrementation 35 // of this read pointer does not require atomic_increment as there is 36 // no concurrent access for this pointer. 10 37 // 11 38 // The SEG_IOC_BASE virtual address must be defined in the hard_config.h file. … … 74 101 75 102 /////////////////////////////////////////////////////////////////////////////////// 76 // Data structure s for command list array103 // Data structure for command descriptor in command list 77 104 /////////////////////////////////////////////////////////////////////////////////// 78 105 … … 92 119 } hba_cmd_desc_t; 93 120 94 typedef struct hba_cmd_list_s // size = 512 bytes95 {96 // 32 command descriptors97 hba_cmd_desc_t desc[32];98 99 } hba_cmd_list_t;100 101 121 /////////////////////////////////////////////////////////////////////////////////// 102 122 // access functions … … 110 130 // - the command tables physical addresses array, 111 131 /////////////////////////////////////////////////////////////////////////////////// 112 extern unsigned int _hba_init ( unsigned int channel);132 extern unsigned int _hba_init (); 113 133 114 134 /////////////////////////////////////////////////////////////////////////////////// 115 // This function register a writecommand in Command List and Command Table135 // This function register a command in Command List and Command Table 116 136 // for a single physical buffer, and updates the HBA_PXCI register. 117 137 // Returns 0 if success, > 0 if error. 118 138 /////////////////////////////////////////////////////////////////////////////////// 119 extern unsigned int _hba_ write( unsigned int channel, // channel index120 unsigned int mode, // BOOT / KERNEL / USER121 unsigned int lba, // logic bloc address on device122 unsigned long long paddr, // memory buffer base address123 unsigned int count ); // number of blocs139 extern unsigned int _hba_access( unsigned int use_irq, 140 unsigned int to_mem, 141 unsigned int lba, 142 unsigned long long paddr, 143 unsigned int count ); 124 144 125 ////////////////////////////////////////////////////////////////////////////////// 126 // This function register a read command in Command List and Command Table 127 // for a single physical buffer, and updates the HBA_PXCI register. 128 // Returns 0 if success, > 0 if error. 129 ////////////////////////////////////////////////////////////////////////////////// 130 extern unsigned int _hba_read ( unsigned int channel, // channel index 131 unsigned int mode, // BOOT / KERNEL / USER 132 unsigned int lba, // logic bloc address on device 133 unsigned long long paddr, // memory buffer base address 134 unsigned int count ); // number of blocks 135 136 ///////////////////////////////////////////////////////////////////////////////// 137 // This function returns the block_size of HBA controller 138 ///////////////////////////////////////////////////////////////////////////////// 139 extern unsigned int _hba_get_block_size (); 140 141 ///////////////////////////////////////////////////////////////////////////////////// 142 // This function returns the content of the HBA_PXIS register for a given channel, 143 // and reset this register to acknoledge IRQ. 144 // return 0 if success, > 0 if error 145 ///////////////////////////////////////////////////////////////////////////////////// 146 extern unsigned int _hba_get_status( unsigned int channel ); 147 148 145 /////////////////////////////////////////////////////////////////////////////////// 146 // Interrupt Service Routine executed in descheduling mode. 147 /////////////////////////////////////////////////////////////////////////////////// 148 extern void _hba_isr( unsigned int irq_type, 149 unsigned int irq_id, 150 unsigned int channel ); 149 151 #endif 150 152 -
soft/giet_vm/giet_drivers/mwr_driver.c
r518 r529 11 11 #include <mwr_driver.h> 12 12 #include <utils.h> 13 #include <kernel_locks.h> 13 14 #include <tty0.h> 14 15 #include <io.h> … … 38 39 #endif 39 40 40 extern unsigned int _coproc_done[X_SIZE*Y_SIZE]; 41 42 ///////////////////////////////////////////////////////////////////////////// 43 // Global variables 44 ///////////////////////////////////////////////////////////////////////////// 45 46 __attribute__((section(".kdata"))) 47 simple_lock_t _coproc_lock[X_SIZE*Y_SIZE]; 48 49 __attribute__((section(".kdata"))) 50 unsigned int _coproc_done[X_SIZE*Y_SIZE]; 41 51 42 52 ///////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/rdk_driver.c
r456 r529 1 /////////////////////////////////////////////////////////////////////////////// ////1 /////////////////////////////////////////////////////////////////////////////// 2 2 // File : rdk_driver.c 3 3 // Date : 13/02/2014 … … 5 5 // Maintainer: cesar fuguet 6 6 // Copyright (c) UPMC-LIP6 7 /////////////////////////////////////////////////////////////////////////////// ////7 /////////////////////////////////////////////////////////////////////////////// 8 8 9 9 #include <giet_config.h> … … 17 17 #endif 18 18 19 ////////////////////////////////////////////// 20 unsigned int _rdk_init( unsigned int channel ) 21 { 22 return 0; 23 } 24 25 ////////////////////////////////////////// 26 unsigned int _rdk_read( unsigned int lba, 27 unsigned int buffer, 28 unsigned int count) 19 ///////////////////////////////////////////////////// 20 unsigned int _rdk_access( unsigned int use_irq, // not used 21 unsigned int to_mem, 22 unsigned int lba, 23 unsigned long long buf_vaddr, // actually vaddr 24 unsigned int count) 29 25 { 30 26 #if USE_IOC_RDK 31 27 32 28 #if GIET_DEBUG_IOC_DRIVER 33 _puts("\n[IOC DEBUG] Enter _rdk_read() at cycle "); 34 _putd( _get_proctime() ); 35 _puts("\n - vaddr = "); 36 _putx( buffer ); 37 -puts("\n - sectors = "); 38 _putd( count ); 39 -puts("\n - lba = "); 40 _putx( lba ); 41 _puts("\n"); 29 unsigned int procid = _get_procid(); 30 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 31 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1); 32 unsigned int p = procid & ((1<<P_WIDTH)-1); 33 _printf("\n[RDK DEBUG] P[%d,%d,%d] enters _rdk_access at cycle %d\n" 34 " use_irq = %d / to_mem = %d / lba = %x / paddr = %x / count = %d\n", 35 x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_vaddr, count ); 42 36 #endif 43 37 44 char* src = (char*)SEG_RDK_BASE + (512*lba); 45 char* dst = (char*)buffer; 46 memcpy( dst, src, count*512 ); 38 char* rdk = (char*)SEG_RDK_BASE + (512*lba); 39 char* buf = (char*)buf_paddr; 40 41 if ( to_mem ) memcpy( buf, rdk, count*512 ); 42 else memcpy( rdk, buf, count*512 ); 43 47 44 return 0; 48 45 49 46 #else 50 47 51 _p uts("[GIET ERROR] _rdk_read() should not be used ifUSE_IOC_RDK not set\n");48 _printf("[RDK ERROR] _rdk_access() but USE_IOC_RDK not set\n"); 52 49 return 1; 53 50 54 51 #endif 55 52 } 56 57 //////////////////////////////////////////58 unsigned int _rdk_write( unsigned int lba,59 unsigned int buffer,60 unsigned int count )61 {62 #if USE_IOC_RDK63 64 #if GIET_DEBUG_IOC_DRIVER65 _puts("\n[IOC DEBUG] Enter _rdk_write() at cycle ");66 _putd( _get_proctime() );67 _puts("\n - vaddr = ");68 _putx( buffer );69 -puts("\n - sectors = ");70 _putd( count );71 -puts("\n - lba = ");72 _putx( lba );73 _puts("\n");74 #endif75 76 char* dst = (char*)SEG_RDK_BASE + (512*lba);77 char* src = (char*)buffer;78 memcpy( dst, src, count*512 );79 return 0;80 81 #else82 83 _puts("[GIET ERROR] _rdk_write() should not be used if USE_IOC_RDK not set\n");84 return 1;85 86 #endif87 }88 89 //////////////////////////////////90 unsigned int _rdk_get_block_size()91 {92 return 512;93 }94 95 //////////////////////////////96 unsigned int _rdk_get_status()97 {98 return 0;99 }100 101 53 102 54 // Local Variables: -
soft/giet_vm/giet_drivers/rdk_driver.h
r437 r529 1 /////////////////////////////////////////////////////////////////////////////// ////1 /////////////////////////////////////////////////////////////////////////////// 2 2 // File : rdk_driver.h 3 3 // Date : 13/02/2014 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////// ////6 /////////////////////////////////////////////////////////////////////////////// 7 7 // The rdk_driver.c and rdk_driver.h files are part ot the GIET-VM kernel. 8 8 // … … 10 10 // in the physical address space. 11 11 // 12 // The _rdk_read() and _rdk_write() blocking functions use a software memcpy, 13 // whatever the selected mode. They return only when the transfer is completed. 14 // As the number of concurrent accesses is not bounded, these functions 15 // don't use the _ioc_lock variable. 12 // The _rdk_access() function use a software memcpy to implement both the read 13 // and write accesses, whatever the selected IRQ mode. It returns only when 14 // the transfer is completed. The memory buffer address is a virtual address. 15 // 16 // As the number of concurrent accesses is not bounded, it does not use any lock. 16 17 // 17 18 // The SEG_RDK_BASE virtual address must be defined in the hard_config.h 18 19 // file when the USE_RAMDISK flag is set. 19 /////////////////////////////////////////////////////////////////////////////// ////20 /////////////////////////////////////////////////////////////////////////////// 20 21 21 22 #ifndef _GIET_RDK_DRIVERS_H_ 22 23 #define _GIET_RDK_DRIVERS_H_ 23 24 24 ///////////////////////////////////////////////////////////////////////////////////25 // BDV access functions and variables (vci_block_device)26 ///////////////////////////////////////////////////////////////////////////////////27 28 25 /////////////////////////////////////////////////////////////////////////////// 29 // This function does nothing, but is required by the IOC API. 30 /////////////////////////////////////////////////////////////////////////////// 31 extern unsigned int _rdk_init(); 32 33 /////////////////////////////////////////////////////////////////////////////// 34 // Transfer data from a memory buffer to the RAMDISK. 35 // - mode : BOOT / KERNEL / USER (unused) 36 // - lba : first block index on the block device 37 // - buffer : virtual base address of the memory buffer 38 // - count : number of blocks to be transfered. 26 // Transfer data between a memory buffer and the RAMDISK. 27 // - use_irq : not used: accees is always synchronous. 28 // - to_mem : to memory buffer when non zero 29 // - lba : first block index on the block device 30 // - buf_vaddr : virtual base address of the memory buffer 31 // - count : number of blocks to be transfered. 39 32 // Returns 0 if success, > 0 if error. 40 33 /////////////////////////////////////////////////////////////////////////////// 41 extern unsigned int _rdk_write( unsigned int lba, 42 unsigned int buffer, 43 unsigned int count ); 44 45 /////////////////////////////////////////////////////////////////////////////// 46 // Transfer data from the RAMDISK to a memory buffer. 47 // - mode : BOOT / KERNEL / USER (unused) 48 // - lba : first block index on the block device 49 // - buffer : virtual base address of the memory buffer 50 // - count : number of blocks to be transfered. 51 // Returns 0 if success, > 0 if error. 52 /////////////////////////////////////////////////////////////////////////////// 53 extern unsigned int _rdk_read( unsigned int lba, 54 unsigned int buffer, 55 unsigned int count ); 56 57 /////////////////////////////////////////////////////////////////////////////// 58 // This function returns the block size. 59 /////////////////////////////////////////////////////////////////////////////// 60 extern unsigned int _rdk_get_block_size(); 61 62 /////////////////////////////////////////////////////////////////////////////////// 63 // This function returns always 0, but is required by the IOC API. 64 /////////////////////////////////////////////////////////////////////////////// 65 extern unsigned int _rdk_get_status(); 34 extern unsigned int _rdk_access( unsigned int use_irq, 35 unsigned int to_mem, 36 unsigned int lba, 37 unsigned long long buf_vaddr, 38 unsigned int count ); 66 39 67 40 #endif -
soft/giet_vm/giet_drivers/sdc_driver.c
r456 r529 372 372 if (sdcard_rsp) 373 373 { 374 _puts("[SDC ERROR] During SD card block leninitialization\n");374 _puts("[SDC ERROR] During SD card block size initialization\n"); 375 375 _exit(); 376 376 } … … 389 389 390 390 return 0; 391 } 392 393 394 ////////////////////////////////////////// 395 unsigned int _sdc_read( unsigned int mode, 396 unsigned int lba, 397 paddr_t buffer, 398 unsigned int count ) 391 } // end _sdc_init() 392 393 394 ///////////////////////////////////////////////////// 395 unsigned int _sdc_access( unsigned int use_irq, // unused 396 unsigned int to_mem, 397 unsigned int lba, 398 unsigned long long buf_paddr, 399 unsigned int count ) 399 400 { 400 401 unsigned char args[4]; … … 404 405 unsigned int last = lba + count; 405 406 406 for ( ; curr < last ; curr++ ) 407 { 408 _sdc_lseek(curr); 409 410 for (i = 0; i < 4; i++) 411 { 412 args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF; 407 if ( to_mem ) // read access 408 { 409 for ( ; curr < last ; curr++ ) 410 { 411 _sdc_lseek(curr); 412 413 for (i = 0; i < 4; i++) 414 { 415 args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF; 416 } 417 418 _sdc_enable(); 419 420 sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00); 421 if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) ) 422 { 423 _sdc_disable(); 424 return sdcard_rsp; 425 } 426 427 _sdc_wait_data_block(); 428 429 if (spi_get_data(sdcard.spi, buf_paddr, 512 )) 430 { 431 _sdc_disable(); 432 return 1; 433 } 434 435 // Get the CRC16 (comes at the end of the data block) 436 _sdc_receive_char(); // first byte 437 _sdc_receive_char(); // second byte 438 439 _sdc_disable(); 440 441 buf_paddr += 512; 413 442 } 414 415 _sdc_enable(); 416 417 sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00); 418 if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) ) 419 { 420 _sdc_disable(); 421 return sdcard_rsp; 422 } 423 424 _sdc_wait_data_block(); 425 426 if (spi_get_data(sdcard.spi, buffer, 512 )) 427 { 428 _sdc_disable(); 429 return 1; 430 } 431 432 // Get the CRC16 (comes at the end of the data block) 433 _sdc_receive_char(); // first byte 434 _sdc_receive_char(); // second byte 435 436 _sdc_disable(); 437 438 buffer += 512; 443 } 444 else // write access 445 { 446 _printf("[SDC ERROR] function _sdc_write() not iplemented yet\n"); 447 _exit(); 439 448 } 440 449 441 450 return 0; 442 } 443 444 /////////////////////////////////////////// 445 unsigned int _sdc_write( unsigned int mode, 446 unsigned int lba, 447 paddr_t buffer, 448 unsigned int count ) 449 { 450 _puts("[SDC ERROR] function _sdc_write() not iplemented yet\n"); 451 _exit(); 452 453 return 0; // to avoid a warning 454 } 455 456 ////////////////////////////// 457 unsigned int _sdc_get_status() 458 { 459 _puts("[SDC ERROR] function _sdc_get_status() should not be called\n"); 460 _exit(); 461 462 return 0; // to avoid a warning 463 } 464 465 ////////////////////////////////// 466 unsigned int _sdc_get_block_size() 467 { 468 if (sdcard.sdhc) return sdcard.block_length*512; 469 else return sdcard.block_length; 470 } 451 } // _end sdc_access() 471 452 472 453 // Local Variables: -
soft/giet_vm/giet_drivers/sdc_driver.h
r437 r529 46 46 47 47 /////////////////////////////////////////////////////////////////////////////// 48 // Transfer data from the block device to a memory buffer. 49 // - mode : BOOT / KERNEL / USER 50 // - lba : first block index on the block device 51 // - buffer : base address of the memory buffer (must be word aligned) 52 // - count : number of blocks to be transfered. 48 // Transfer data between the block device and a memory buffer. 49 // - use_irq : not used, as DMA is not supported yet 50 // - to_mem : to memory if non zero 51 // - lba : first block index on the block device 52 // - buf_vaddr : base address of the memory buffer 53 // - count : number of blocks to be transfered. 53 54 // Returns 0 if success, > 0 if error. 54 55 /////////////////////////////////////////////////////////////////////////////// 55 unsigned int _sdc_read( unsigned int mode, 56 unsigned int lba, 57 paddr_t buffer, 58 unsigned int count); 59 60 61 /////////////////////////////////////////////////////////////////////////////// 62 // Transfer data from memory buffer to SD card device. 63 // - mode : BOOT / KERNEL / USER 64 // - lba : destination first block index on the SD card 65 // - buffer : base address of the memory buffer (must be word aligned) 66 // - count : number of blocks to be transfered. 67 // Returns 0 if success, > 0 if error. 68 // WARNING: The _sdc_write() is not implemented yet. 69 /////////////////////////////////////////////////////////////////////////////// 70 unsigned int _sdc_write( unsigned int mode, 71 unsigned int lba, 72 paddr_t buffer, 73 unsigned int count); 74 75 /////////////////////////////////////////////////////////////////////////////// 76 // This function should not be called for the SDC card. 77 /////////////////////////////////////////////////////////////////////////////// 78 unsigned int _sdc_get_status(); 79 80 /////////////////////////////////////////////////////////////////////////////// 81 // Returns the block size in bytes of the SD card. 82 /////////////////////////////////////////////////////////////////////////////// 83 unsigned int _sdc_get_block_size(); 84 56 unsigned int _sdc_access( unsigned int use_irq, 57 unsigned int to_mem, 58 unsigned int lba, 59 unsigned long long buf_vaddr, 60 unsigned int count); 85 61 86 62 /////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_drivers/tim_driver.c
r456 r529 1 ///////////////////////////////////////////////////////////////////////////// /////////1 ///////////////////////////////////////////////////////////////////////////// 2 2 // File : tim_driver.c 3 3 // Date : 23/05/2013 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 ///////////////////////////////////////////////////////////////////////////// /////////6 ///////////////////////////////////////////////////////////////////////////// 7 7 8 8 #include <giet_config.h> … … 48 48 #endif 49 49 50 ///////////////////////////////////////////////////////////////////////////// ////50 ///////////////////////////////////////////////////////////////////////////// 51 51 // global variables 52 ///////////////////////////////////////////////////////////////////////////// ////52 ///////////////////////////////////////////////////////////////////////////// 53 53 54 54 #define in_unckdata __attribute__((section (".unckdata"))) … … 59 59 #endif 60 60 61 ///////////////////////////////////////////////////////////////////////////// ////61 ///////////////////////////////////////////////////////////////////////////// 62 62 // access functions 63 ///////////////////////////////////////////////////////////////////////////// ////63 ///////////////////////////////////////////////////////////////////////////// 64 64 65 /////////////////////////////////////////////////////// ///////65 /////////////////////////////////////////////////////// 66 66 unsigned int _timer_get_register( unsigned int channel, 67 67 unsigned int index ) -
soft/giet_vm/giet_drivers/xcu_driver.c
r496 r529 87 87 unsigned int irq_type ) 88 88 { 89 #if USE_XCU90 89 // parameters checking 91 90 unsigned int x = cluster_xy >> Y_WIDTH; … … 106 105 107 106 _xcu_set_register(cluster_xy, func, channel, value); 108 109 #else110 _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XCU not set\n");111 _exit();112 #endif113 107 } 114 108 … … 119 113 unsigned int * irq_type ) 120 114 { 121 #if USE_XCU122 115 // parameters checking 123 116 unsigned int x = cluster_xy >> Y_WIDTH; … … 153 146 *index = 32; 154 147 } 155 156 #else157 _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XCU is not set\n");158 _exit();159 #endif160 148 } 161 149 … … 165 153 unsigned int wdata ) 166 154 { 167 #if USE_XCU168 155 // parameters checking 169 156 unsigned int x = cluster_xy >> Y_WIDTH; … … 174 161 175 162 _xcu_set_register(cluster_xy, XCU_WTI_REG, wti_index, wdata); 176 177 #else178 _printf("[GIET ERROR] _xcu_send_wti() should not be used if USE_XCU is not set\n");179 _exit();180 #endif181 163 } 182 164 … … 186 168 unsigned int wdata ) 187 169 { 188 #if USE_XCU189 170 // parameters checking 190 171 unsigned int x = cluster_xy >> Y_WIDTH; … … 199 180 200 181 _physical_write(paddr, wdata); 201 202 #else 203 _puts("[GIET ERROR] _xcu_send_wti() should not be used if USE_XCU is not set\n"); 204 _exit(); 205 #endif 206 } 182 } 183 207 184 /////////////////////////////////////////////////// 208 185 void _xcu_get_wti_value( unsigned int cluster_xy, … … 210 187 unsigned int * value ) 211 188 { 212 #if USE_XCU213 189 // parameters checking 214 190 unsigned int x = cluster_xy >> Y_WIDTH; … … 219 195 220 196 *value = _xcu_get_register(cluster_xy, XCU_WTI_REG, wti_index); 221 222 #else223 _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XCU is not set\n");224 _exit();225 #endif226 197 } 227 198 … … 230 201 unsigned int * address ) 231 202 { 232 #if USE_XCU 233 if (wti_index >= 32) _exit(); 203 if (wti_index >= 32) _exit(); 234 204 235 205 *address = SEG_XCU_BASE + (XCU_REG(XCU_WTI_REG, wti_index)<<2); 236 237 #else238 _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XCU is not set\n");239 _exit();240 #endif241 206 } 242 207 … … 246 211 unsigned int period ) 247 212 { 248 #if USE_XCU249 213 // parameters checking 250 214 unsigned int x = cluster_xy >> Y_WIDTH; … … 254 218 255 219 _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, period); 256 257 #else258 _printf("[GIET ERROR] in _xcu_timer_start() USE_XCU is not set\n");259 _exit();260 #endif261 220 } 262 221 … … 265 224 unsigned int pti_index) 266 225 { 267 #if USE_XCU268 226 // parameters checking 269 227 unsigned int x = cluster_xy >> Y_WIDTH; … … 273 231 274 232 _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, 0); 275 276 #else277 _printf("[GIET ERROR] in _xcu_timer_stop() USE_XCU is not set\n");278 _exit();279 #endif280 233 } 281 234 282 235 /////////////////////////////////////////////////////////// 283 unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 284 unsigned int pti_index ) 285 { 286 #if USE_XCU 236 void _xcu_timer_reset_irq( unsigned int cluster_xy, 237 unsigned int pti_index ) 238 { 287 239 // parameters checking 288 240 unsigned int x = cluster_xy >> Y_WIDTH; … … 292 244 293 245 // This return value is not used / avoid a compilation warning. 294 return _xcu_get_register(cluster_xy, XCU_PTI_ACK, pti_index); 295 296 #else 297 _puts("[GIET ERROR] in _xcu_timer_reset_irq() USE_XCU is not set\n"); 298 _exit(); 299 return 0; 300 #endif 246 x = _xcu_get_register(cluster_xy, XCU_PTI_ACK, pti_index); 301 247 } 302 248 … … 305 251 unsigned int pti_index ) 306 252 { 307 #if USE_XCU308 253 // parameters checking 309 254 unsigned int x = cluster_xy >> Y_WIDTH; … … 318 263 _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, 0); 319 264 _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, per); 320 321 #else322 _puts("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XCU is not set\n");323 _exit();324 #endif325 265 } 326 266 -
soft/giet_vm/giet_drivers/xcu_driver.h
r490 r529 139 139 // or by the _isr_timer() for an "user" timer. 140 140 ////////////////////////////////////////////////////////////////////////////// 141 extern unsigned int_xcu_timer_reset_irq( unsigned int cluster_xy,142 141 extern void _xcu_timer_reset_irq( unsigned int cluster_xy, 142 unsigned int pti_index ); 143 143 144 144 //////////////////////////////////////////////////////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.