Changeset 165 for soft/giet_vm/sys/drivers.c
- Timestamp:
- Jul 4, 2012, 2:51:18 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/sys/drivers.c
r160 r165 16 16 // 17 17 // The following global parameters must be defined in the giet_config.h file: 18 // - NB_PROCS : number of PROCS per cluster (if not zero) 19 // - NB_DMAS : number of DMA channels per cluster (if not zero) 20 // - NB_TIMERS : number of TIMERS per cluster (if not zero) 21 // - NB_TTYS : number of TTY terminals per cluster (if not zero) 18 // - NB_CLUSTERS : number of clusters 19 // - NB_PROCS : number of PROCS per cluster 20 // - NB_TIMERS : number of TIMERS per cluster 21 // - NB_DMAS : number of DMA channels 22 // - NB_TTYS : number of TTY terminals 23 // - NB_TIMERS : number of TIMERS per cluster 24 // - CLUSTER_SPAN : address increment between clusters 22 25 // 23 26 // The following base addresses must be defined in the sys.ld file: … … 58 61 #endif 59 62 63 #if (NB_TTYS < 1) 64 # error: NB_TTYS cannot be smaller than 1! 65 #endif 66 67 #if (NB_TIMERS < NB_PROCS) 68 # error: NB_TIMERS must be larger or equal to NB_PROCS! 69 #endif 70 71 #if (NB_PROCS > 8) 72 # error: NB_PROCS cannot be larger than 8! 73 #endif 74 75 #if (NB_DMAS < 1) 76 # error: NB_DMAS cannot be 0! 77 #endif 78 79 60 80 ///////////////////////////////////////////////////////////////////////////// 61 81 // Global (uncachable) variables … … 71 91 in_unckdata volatile unsigned int _ioc_lock = 0; 72 92 73 in_unckdata volatile unsigned int _tty_lock[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 };74 93 in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS]; 75 94 in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 }; 95 in_unckdata unsigned int _tty_put_lock; 76 96 77 97 ////////////////////////////////////////////////////////////////////////////// 78 98 // VciMultiTimer driver 79 99 ////////////////////////////////////////////////////////////////////////////// 80 // The number of independant timers per cluster is defined by the 81 // configuration parameter NB_TIMERS. 100 // There is one MULTI-TIMER component per cluster. 101 // The number of timers per cluster must be larger or equal to the number 102 // processors (NB_TIMERS >= NB_PROCS), because each processor uses a private 103 // yimer for context switch. 82 104 // The total number of timers is NB_CLUSTERS * NB_TIMERS 83 // The global timer index = cluster_id*NB_TIMER + timer_id105 // The global timer index = cluster_id*NB_TIMERS + timer_id 84 106 ////////////////////////////////////////////////////////////////////////////// 85 107 … … 87 109 // _timer_write() 88 110 // 89 // Write a 32-bit word in a memory mapped register of a timer device. 90 // Returns 0 if success, > 0 if error. 91 ////////////////////////////////////////////////////////////////////////////// 92 unsigned int _timer_write( unsigned int global_timer_index, 111 // Write a 32-bit word in a memory mapped register of a timer device, 112 // identified by the cluster index and the local timer index. 113 // Returns 0 if success, > 0 if error. 114 ////////////////////////////////////////////////////////////////////////////// 115 unsigned int _timer_write( unsigned int cluster_index, 116 unsigned int timer_index, 93 117 unsigned int register_index, 94 118 unsigned int value ) 95 119 { 96 volatile unsigned int *timer_address; 97 98 unsigned int cluster_id = global_timer_index / NB_TIMERS; 99 unsigned int timer_id = global_timer_index % NB_TIMERS; 100 101 /* parameters checking */ 102 if ( register_index >= TIMER_SPAN) return 1; 103 if ( global_timer_index >= NB_CLUSTERS*NB_TIMERS ) return 1; 120 unsigned int* timer_address; 121 122 // parameters checking 123 if ( register_index >= TIMER_SPAN) return 1; 124 if ( cluster_index >= NB_CLUSTERS) return 1; 125 if ( timer_index >= NB_TIMERS ) return 1; 104 126 105 127 timer_address = (unsigned int*)&seg_timer_base + 106 ( cluster_i d* CLUSTER_SPAN ) +107 ( timer_i d* TIMER_SPAN );108 109 timer_address[register_index] = value; / * write word */128 ( cluster_index * CLUSTER_SPAN ) + 129 ( timer_index * TIMER_SPAN ); 130 131 timer_address[register_index] = value; // write word 110 132 111 133 return 0; … … 115 137 // _timer_read() 116 138 // 117 // Read a 32-bit word in a memory mapped register of a timer device. 118 // Returns 0 if success, > 0 if error. 119 ////////////////////////////////////////////////////////////////////////////// 120 unsigned int _timer_read(unsigned int global_timer_index, 139 // Read a 32-bit word in a memory mapped register of a timer device, 140 // identified by the cluster index and the local timer index. 141 // Returns 0 if success, > 0 if error. 142 ////////////////////////////////////////////////////////////////////////////// 143 unsigned int _timer_read(unsigned int cluster_index, 144 unsigned int timer_index, 121 145 unsigned int register_index, 122 146 unsigned int *buffer) 123 147 { 124 volatile unsigned int *timer_address; 125 126 unsigned int cluster_id = global_timer_index / NB_TIMERS; 127 unsigned int timer_id = global_timer_index % NB_TIMERS; 128 129 /* parameters checking */ 130 if ( register_index >= TIMER_SPAN) return 1; 131 if ( global_timer_index >= NB_CLUSTERS*NB_TIMERS ) return 1; 148 unsigned int *timer_address; 149 150 // parameters checking 151 if ( register_index >= TIMER_SPAN) return 1; 152 if ( cluster_index >= NB_CLUSTERS) return 1; 153 if ( timer_index >= NB_TIMERS ) return 1; 132 154 133 155 timer_address = (unsigned int*)&seg_timer_base + 134 ( cluster_i d* CLUSTER_SPAN ) +135 ( timer_i d* TIMER_SPAN );136 137 *buffer = timer_address[register_index]; / * read word */156 ( cluster_index * CLUSTER_SPAN ) + 157 ( timer_index * TIMER_SPAN ); 158 159 *buffer = timer_address[register_index]; // read word 138 160 139 161 return 0; … … 146 168 // The system terminal is TTY[0]. 147 169 // The TTYs are allocated to applications by the GIET in the boot phase. 148 // The nummber of TTYs allocated to each application, and the TTYused by each170 // The nummber of TTYs allocated to each application, and used by each 149 171 // task can be defined in the mapping_info data structure. 150 172 // For each user task, the tty_id is stored in the context of the task (slot 34), … … 152 174 // The TTY address is always computed as : seg_tty_base + tty_id*TTY_SPAN 153 175 /////////////////////////////////////////////////////////////////////////////////// 154 155 ///////////////////////////////////////////////////////////////////////////////////156 // tty_get_lock()157 //158 // This blocking function is intended to be used by the _tty_write() function159 // to provide exclusive access to the TTY. It is not used yet, because it appears160 // that it creates livelock situations...161 ///////////////////////////////////////////////////////////////////////////////////162 static inline void _tty_get_lock( unsigned int tty_id )163 {164 register unsigned int delay = (_proctime() & 0xF) << 4;165 register unsigned int *plock = (unsigned int*)&_tty_lock[tty_id];166 167 asm volatile (168 "_tty_llsc: \n"169 "ll $2, 0(%0) \n" /* $2 <= _tty_lock current value */170 "bnez $2, _tty_delay \n" /* delay if _tty_lock already taken */171 "li $3, 1 \n" /* $3 <= argument for sc */172 "sc $3, 0(%0) \n" /* try to set _tty_lock */173 "bnez $3, _tty_ok \n" /* exit if atomic */174 "_tty_delay: \n"175 "move $4, %1 \n" /* $4 <= delay */176 "_tty_loop: \n"177 "addi $4, $4, -1 \n" /* $4 <= $4 - 1 */178 "beqz $4, _tty_loop \n" /* test end delay */179 "j _tty_llsc \n" /* retry */180 "_tty_ok: \n"181 :182 :"r"(plock), "r"(delay)183 :"$2", "$3", "$4");184 }185 176 186 177 ////////////////////////////////////////////////////////////////////////////// … … 194 185 // The function returns the number of characters that have been written. 195 186 ////////////////////////////////////////////////////////////////////////////// 196 unsigned int _tty_write(const char *buffer, unsigned int length) 187 unsigned int _tty_write( const char *buffer, 188 unsigned int length) 197 189 { 198 190 volatile unsigned int *tty_address; … … 212 204 for (nwritten = 0; nwritten < length; nwritten++) 213 205 { 214 / * check tty's status */206 // check tty's status 215 207 if ((tty_address[TTY_STATUS] & 0x2) == 0x2) 216 208 break; 217 209 else 218 / * write character */210 // write character 219 211 tty_address[TTY_WRITE] = (unsigned int)buffer[nwritten]; 220 212 } … … 226 218 // 227 219 // This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and 228 // the associated //kernel buffer, that has been written by the ISR.220 // the associated kernel buffer, that has been written by the ISR. 229 221 // It fetches one single character from the _tty_get_buf[tty_id] kernel 230 222 // buffer, writes this character to the user buffer, and resets the … … 232 224 // Returns 0 if the kernel buffer is empty, 1 if the buffer is full. 233 225 ////////////////////////////////////////////////////////////////////////////// 234 unsigned int _tty_read_irq(char *buffer, unsigned int length) 226 unsigned int _tty_read_irq( char *buffer, 227 unsigned int length) 235 228 { 236 229 unsigned int proc_id; … … 262 255 // register of the TTY controler, and writes this character to the user buffer. 263 256 // It doesn't use the TTY_GET_IRQ interrupt and the associated kernel buffer. 264 // It doesn't take the lock protecting exclusive access...265 257 // Returns 0 if the register is empty, 1 if the register is full. 266 258 //////////////////////////////////////////////////////////////////////////////// 267 unsigned int _tty_read(char *buffer, unsigned int length) 259 unsigned int _tty_read( char *buffer, 260 unsigned int length) 268 261 { 269 262 volatile unsigned int *tty_address; … … 296 289 // _icu_write() 297 290 // 298 // Write a 32-bit word in a memory mapped register of the ICU device. The 299 // base address is deduced by the proc_id. 300 // Returns 0 if success, > 0 if error. 301 //////////////////////////////////////////////////////////////////////////////// 302 unsigned int _icu_write(unsigned int register_index, unsigned int value) 303 { 304 volatile unsigned int *icu_address; 305 unsigned int proc_id; 306 307 /* parameters checking */ 308 if (register_index >= ICU_END) 309 return 1; 310 311 proc_id = _procid(); 312 icu_address = (unsigned int*)&seg_icu_base + (proc_id * ICU_SPAN); 313 icu_address[register_index] = value; /* write word */ 291 // Write a 32-bit word in a memory mapped register of the MULTI_ICU device, 292 // identified by the cluster index, and a processor local index. 293 // Returns 0 if success, > 0 if error. 294 //////////////////////////////////////////////////////////////////////////////// 295 unsigned int _icu_write( unsigned int cluster_index, 296 unsigned int proc_index, 297 unsigned int register_index, 298 unsigned int value ) 299 { 300 unsigned int *icu_address; 301 302 // parameters checking 303 if ( register_index >= ICU_SPAN) return 1; 304 if ( cluster_index >= NB_CLUSTERS) return 1; 305 if ( proc_index >= NB_PROCS ) return 1; 306 307 icu_address = (unsigned int*)&seg_icu_base + 308 ( cluster_index * CLUSTER_SPAN ) + 309 ( proc_index * ICU_SPAN ); 310 311 icu_address[register_index] = value; // write word 314 312 return 0; 315 313 } … … 318 316 // _icu_read() 319 317 // 320 // Read a 32-bit word in a memory mapped register of the ICU device. The 321 // ICU base address is deduced by the proc_id. 322 // Returns 0 if success, > 0 if error. 323 //////////////////////////////////////////////////////////////////////////////// 324 unsigned int _icu_read(unsigned int register_index, unsigned int *buffer) 325 { 326 volatile unsigned int *icu_address; 327 unsigned int proc_id; 328 329 /* parameters checking */ 330 if (register_index >= ICU_END) 331 return 1; 332 333 proc_id = _procid(); 334 icu_address = (unsigned int*)&seg_icu_base + (proc_id * ICU_SPAN); 335 *buffer = icu_address[register_index]; /* read word */ 318 // Read a 32-bit word in a memory mapped register of the MULTI_ICU device, 319 // identified by the cluster index and a processor local index. 320 // Returns 0 if success, > 0 if error. 321 //////////////////////////////////////////////////////////////////////////////// 322 unsigned int _icu_read( unsigned int cluster_index, 323 unsigned int proc_index, 324 unsigned int register_index, 325 unsigned int* buffer ) 326 { 327 unsigned int *icu_address; 328 329 // parameters checking 330 if ( register_index >= ICU_SPAN) return 1; 331 if ( cluster_index >= NB_CLUSTERS) return 1; 332 if ( proc_index >= NB_PROCS ) return 1; 333 334 icu_address = (unsigned int*)&seg_icu_base + 335 ( cluster_index * CLUSTER_SPAN ) + 336 ( proc_index * ICU_SPAN ); 337 338 *buffer = icu_address[register_index]; // read word 336 339 return 0; 337 340 } … … 341 344 //////////////////////////////////////////////////////////////////////////////// 342 345 // The Greater Dommon Divider is a -very- simple hardware coprocessor 343 // performing the computation of aGCD of two 32 bits integers.346 // performing the computation of the GCD of two 32 bits integers. 344 347 // It has no DMA capability. 345 348 //////////////////////////////////////////////////////////////////////////////// … … 351 354 // Returns 0 if success, > 0 if error. 352 355 //////////////////////////////////////////////////////////////////////////////// 353 unsigned int _gcd_write(unsigned int register_index, unsigned int value) 356 unsigned int _gcd_write( unsigned int register_index, 357 unsigned int value) 354 358 { 355 359 volatile unsigned int *gcd_address; 356 360 357 / * parameters checking */361 // parameters checking 358 362 if (register_index >= GCD_END) 359 363 return 1; 360 364 361 365 gcd_address = (unsigned int*)&seg_gcd_base; 362 gcd_address[register_index] = value; /* write word */ 366 367 gcd_address[register_index] = value; // write word 363 368 return 0; 364 369 } … … 370 375 // Returns 0 if success, > 0 if error. 371 376 //////////////////////////////////////////////////////////////////////////////// 372 unsigned int _gcd_read(unsigned int register_index, unsigned int *buffer) 377 unsigned int _gcd_read( unsigned int register_index, 378 unsigned int *buffer) 373 379 { 374 380 volatile unsigned int *gcd_address; 375 381 376 / * parameters checking */382 // parameters checking 377 383 if (register_index >= GCD_END) 378 384 return 1; 379 385 380 386 gcd_address = (unsigned int*)&seg_gcd_base; 381 *buffer = gcd_address[register_index]; /* read word */ 387 388 *buffer = gcd_address[register_index]; // read word 382 389 return 0; 383 390 } … … 386 393 // VciBlockDevice driver 387 394 //////////////////////////////////////////////////////////////////////////////// 388 // The VciBlockDevice is a si mpleexternal storage contrÃŽler.395 // The VciBlockDevice is a single channel external storage contrÃŽler. 389 396 // The three functions below use the three variables _ioc_lock _ioc_done, and 390 // _ioc_status for synchron sation.397 // _ioc_status for synchronisation. 391 398 // As the IOC component can be used by several programs running in parallel, 392 399 // the _ioc_lock variable guaranties exclusive access to the device. The … … 429 436 "move $4, %1 \n" /* $4 <= delay */ 430 437 "_ioc_loop: \n" 438 "beqz $4, _ioc_loop \n" /* test end delay */ 431 439 "addi $4, $4, -1 \n" /* $4 <= $4 - 1 */ 432 " beqz $4, _ioc_loop \n" /* test end delay*/433 " j _ioc_llsc \n" /* retry */440 "j _ioc_llsc \n" /* retry ll */ 441 "nop \n" 434 442 "_ioc_ok: \n" 435 443 :
Note: See TracChangeset
for help on using the changeset viewer.