Changeset 203 for soft/giet_vm/sys/drivers.c
- Timestamp:
- Aug 13, 2012, 10:52:25 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/sys/drivers.c
r199 r203 11 11 // - vci_multi_dma 12 12 // - vci_multi_icu 13 // - vci_xicu 13 // - vci_xicu & vci_multi_icu 14 14 // - vci_gcd 15 15 // - vci_frame_buffer … … 23 23 // - NB_TTYS 24 24 // 25 // The following base addresses must be defined in the sys.ld file:25 // The following virtual base addresses must be defined in the sys.ld file: 26 26 // - seg_icu_base 27 // - seg_tim er_base27 // - seg_tim_base 28 28 // - seg_tty_base 29 29 // - seg_gcd_base 30 30 // - seg_dma_base 31 // - seg_fb _base31 // - seg_fbf_base 32 32 // - seg_ioc_base 33 33 /////////////////////////////////////////////////////////////////////////////////// … … 93 93 #define in_unckdata __attribute__((section (".unckdata"))) 94 94 95 96 95 ////////////////////////////////////////////////////////////////////////////// 97 // VciMultiTimerdriver96 // Timers driver 98 97 ////////////////////////////////////////////////////////////////////////////// 99 // There is one multi_timer (or xicu) component per cluster. 100 // The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id 98 // The timers can be implemented in a vci_timer component or in a vci_xicu 99 // component (depending on the GIET_USE_XICU parameter). 100 // There is one timer (or xicu) component per cluster. 101 101 // There is two types of timers: 102 102 // - "system" timers : one per processor, used for context switch. 103 103 // local_id in [0, NB_PROCS_MAX-1], 104 104 // - "user" timers : requested by the task in the mapping_info data structure. 105 // local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1], 106 // For each user timer, the tty_id is stored in the context of the task 107 // and must be explicitely defined in the boot code. 108 // These timers can be implemented in a vci_multi_timer component 109 // or in a vci_xicu component (depending on the GIET_USE_XICU parameter). 105 // local_id in [NB_PROC_MAX, NB_PROCS_MAX + NB_TIMERS_MAX - 1] 106 // For each user timer, the timer_id is stored in the context of the task. 107 // The global index is cluster_id * (NB_PROCS_MAX+NB_TIMERS_MAX) + local_id 110 108 ////////////////////////////////////////////////////////////////////////////// 111 109 … … 118 116 119 117 ////////////////////////////////////////////////////////////////////////////// 120 // _timer_ access()121 // This function is the only way to access a timer device.122 // It can be a multi-timer component or an xicu component.123 // It can be used by the kernel to initialise a "system" timer,118 // _timer_start() 119 // This function activates a timer in the vci_timer (or vci_xicu) component 120 // by writing in the proper register the period value. 121 // It can be used by both the kernel to initialise a "system" timer, 124 122 // or by a task (through a system call) to configure an "user" timer. 125 123 // Returns 0 if success, > 0 if error. 126 124 ////////////////////////////////////////////////////////////////////////////// 127 unsigned int _timer_access( unsigned int read, 128 unsigned int cluster_id, 129 unsigned int local_id, 130 unsigned int register_id, 131 unsigned int* buffer ) 125 unsigned int _timer_start( unsigned int cluster_id, 126 unsigned int local_id, 127 unsigned int period ) 132 128 { 133 129 // parameters checking 134 if ( register_id >= TIMER_SPAN) return 1;135 130 if ( cluster_id >= NB_CLUSTERS) return 1; 136 131 if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1; 137 132 138 133 #if GIET_USE_XICU 139 140 unsigned int* timer_address = //TODO 141 134 unsigned int* timer_address = (unsigned int*)&seg_icu_base + 135 (cluster_id * CLUSTER_SPAN); 136 137 timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period; 142 138 #else 143 144 unsigned int* timer_address = (unsigned int*)&seg_timer_base + 145 (cluster_id * CLUSTER_SPAN) + 146 (local_id * TIMER_SPAN); 147 #endif 148 149 if (read) *buffer = timer_address[register_id]; // read word 150 else timer_address[register_id] = *buffer; // write word 139 unsigned int* timer_address = (unsigned int*)&seg_tim_base + 140 (cluster_id * CLUSTER_SPAN); 141 142 timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period; 143 timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3; 144 #endif 145 151 146 return 0; 152 147 } 153 148 ////////////////////////////////////////////////////////////////////////////// 154 // _timer_write() 155 // This function implements a write access to a "user" timer register. 156 // It gets the cluster_id and local_id from the global index stored in 157 // the task context and use the timer_access() function to make the write. 149 // _timer_stop() 150 // This function desactivates a timer in the vci_timer (or vci_xicu) component 151 // by writing in the proper register. 158 152 // Returns 0 if success, > 0 if error. 159 153 ////////////////////////////////////////////////////////////////////////////// 160 unsigned int _timer_write( unsigned int register_id, 161 unsigned int value ) 162 { 163 unsigned int buffer = value; 164 unsigned int task_id = _get_current_task_id(); 165 unsigned int timer_id = _get_context_slot(task_id, CTX_TIMER_ID); 166 unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX); 167 unsigned int local_id = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX); 168 169 // checking user timer 170 if ( local_id < NB_PROCS_MAX ) 171 { 172 return 2; 173 } 174 else 175 { 176 return _timer_access ( 0, // write access 177 cluster_id, 178 local_id, 179 register_id, 180 &buffer ); 181 } 154 unsigned int _timer_stop( unsigned int cluster_id, 155 unsigned int local_id ) 156 { 157 // parameters checking 158 if ( cluster_id >= NB_CLUSTERS) return 1; 159 if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1; 160 161 #if GIET_USE_XICU 162 unsigned int* timer_address = (unsigned int*)&seg_icu_base + 163 (cluster_id * CLUSTER_SPAN); 164 165 timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0; 166 #else 167 unsigned int* timer_address = (unsigned int*)&seg_tim_base + 168 (cluster_id * CLUSTER_SPAN); 169 170 timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0; 171 #endif 172 173 return 0; 182 174 } 183 175 ////////////////////////////////////////////////////////////////////////////// 184 // _timer_read() 185 // This function implements a read access to a "user" timer register. 186 // It gets the cluster_id and local_id from the global index stored in 187 // the task context and use the timer_access() function to make the read. 176 // _timer_reset_irq() 177 // This function acknowlegge a timer interrupt in the vci_timer (or vci_xicu) 178 // component by writing in the proper register the period value. 179 // It can be used by both the isr_switch() for a "system" timer, 180 // or by the _isr_timer() for an "user" timer. 188 181 // Returns 0 if success, > 0 if error. 189 182 ////////////////////////////////////////////////////////////////////////////// 190 unsigned int _timer_read( unsigned int register_id, 191 unsigned int* buffer ) 192 { 193 unsigned int task_id = _get_current_task_id(); 194 unsigned int timer_id = _get_context_slot(task_id, CTX_TIMER_ID); 195 unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX); 196 unsigned int local_id = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX); 197 198 // checking user timer 199 if ( local_id < NB_PROCS_MAX ) 200 { 201 return 2; 202 } 203 else 204 { 205 return _timer_access ( 1, // read access 206 cluster_id, 207 local_id, 208 register_id, 209 buffer ); 210 } 211 } 212 ///////////////////////////////////////////////////////////////////////////////// 213 // _timer_check() 214 ///////////////////////////////////////////////////////////////////////////////// 183 unsigned int _timer_reset_irq( unsigned int cluster_id, 184 unsigned int local_id ) 185 { 186 // parameters checking 187 if ( cluster_id >= NB_CLUSTERS) return 1; 188 if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1; 189 190 #if GIET_USE_XICU 191 unsigned int* timer_address = (unsigned int*)&seg_icu_base + 192 (cluster_id * CLUSTER_SPAN); 193 194 unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)]; 195 #else 196 unsigned int* timer_address = (unsigned int*)&seg_tim_base + 197 (cluster_id * CLUSTER_SPAN); 198 199 timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0; 200 #endif 201 202 return 0; 203 } 215 204 216 205 ///////////////////////////////////////////////////////////////////////////////// … … 349 338 // VciMultiIcu and VciXicu drivers 350 339 //////////////////////////////////////////////////////////////////////////////// 351 // There is in principle one vci_multi_icu (or vci_xicu) component per cluster, 352 // and the number of independant ICUs is equal to NB_PROCS_MAX, because there is 353 // one private interrupr controler per processor. 354 //////////////////////////////////////////////////////////////////////////////// 355 356 //////////////////////////////////////////////////////////////////////////////// 357 // _icu_write() 358 // Write a 32-bit word in a memory mapped register of the MULTI_ICU device, 359 // identified by the cluster index, and a processor local index. 360 // Returns 0 if success, > 0 if error. 361 //////////////////////////////////////////////////////////////////////////////// 362 unsigned int _icu_write( unsigned int cluster_index, 363 unsigned int proc_index, 364 unsigned int register_index, 365 unsigned int value ) 366 { 340 // There is one vci_multi_icu (or vci_xicu) component per cluster, 341 // and the number of independant ICUs is equal to NB_PROCS_MAX, 342 // because there is one private interrupr controler per processor. 343 //////////////////////////////////////////////////////////////////////////////// 344 345 //////////////////////////////////////////////////////////////////////////////// 346 // _icu_set_mask() 347 // This function can be used with both the vci_xicu & vci_multi_icu components. 348 // It set the mask register for the ICU channel identified by the cluster index 349 // and the processor index: all '1' bits are set / all '0' bits are not modified. 350 // Returns 0 if success, > 0 if error. 351 //////////////////////////////////////////////////////////////////////////////// 352 unsigned int _icu_set_mask( unsigned int cluster_id, 353 unsigned int proc_id, 354 unsigned int value, 355 unsigned int is_timer ) 356 { 357 // parameters checking 358 if ( cluster_id >= NB_CLUSTERS) return 1; 359 if ( proc_id >= NB_PROCS_MAX ) return 1; 360 361 unsigned int* icu_address = (unsigned int*)&seg_icu_base + 362 (cluster_id * CLUSTER_SPAN); 367 363 #if GIET_USE_XICU 368 364 if ( is_timer ) icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value; 365 else icu_address[XICU_REG(XICU_MSK_HWI_ENABLE, proc_id)] = value; 369 366 #else 370 367 icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; 368 #endif 369 370 return 0; 371 } 372 //////////////////////////////////////////////////////////////////////////////// 373 // _icu_get_index() 374 // This function can be used with both the vci_xicu & vci_multi_icu components. 375 // It returns the index of the highest priority (smaller index) active HWI. 376 // The ICU channel is identified by the cluster index and the processor index. 377 // Returns 0 if success, > 0 if error. 378 //////////////////////////////////////////////////////////////////////////////// 379 unsigned int _icu_get_index( unsigned int cluster_id, 380 unsigned int proc_id, 381 unsigned int* buffer ) 382 { 371 383 // parameters checking 372 if ( register_index >= ICU_SPAN) return 1; 373 if ( cluster_index >= NB_CLUSTERS) return 1; 374 if ( proc_index >= NB_PROCS_MAX ) return 1; 375 376 unsigned int *icu_address = (unsigned int*)&seg_icu_base + 377 (cluster_index * CLUSTER_SPAN) + 378 (proc_index * ICU_SPAN); 379 380 icu_address[register_index] = value; // write word 384 if ( cluster_id >= NB_CLUSTERS) return 1; 385 if ( proc_id >= NB_PROCS_MAX ) return 1; 386 387 unsigned int* icu_address = (unsigned int*)&seg_icu_base + 388 (cluster_id * CLUSTER_SPAN); 389 #if GIET_USE_XICU 390 unsigned int prio = icu_address[XICU_REG(XICU_PRIO, proc_id)]; 391 unsigned int pti_ok = (prio & 0x00000001); 392 unsigned int hwi_ok = (prio & 0x00000002); 393 unsigned int swi_ok = (prio & 0x00000004); 394 unsigned int pti_id = (prio & 0x00001F00) >> 8; 395 unsigned int hwi_id = (prio & 0x001F0000) >> 16; 396 unsigned int swi_id = (prio & 0x1F000000) >> 24; 397 if (pti_ok) *buffer = pti_id; 398 else if (hwi_ok) *buffer = hwi_id; 399 else if (swi_ok) *buffer = swi_id; 400 else *buffer = 32; 401 #else 402 *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; 403 #endif 404 381 405 return 0; 382 383 #endif384 }385 ////////////////////////////////////////////////////////////////////////////////386 // _icu_read()387 // Read a 32-bit word in a memory mapped register of the MULTI_ICU device,388 // identified by the cluster index and a processor local index.389 // Returns 0 if success, > 0 if error.390 ////////////////////////////////////////////////////////////////////////////////391 unsigned int _icu_read( unsigned int cluster_index,392 unsigned int proc_index,393 unsigned int register_index,394 unsigned int* buffer )395 {396 #if GIET_USE_XICU397 398 #else399 400 // parameters checking401 if ( register_index >= ICU_SPAN) return 1;402 if ( cluster_index >= NB_CLUSTERS) return 1;403 if ( proc_index >= NB_PROCS_MAX ) return 1;404 405 unsigned int *icu_address = (unsigned int*)&seg_icu_base +406 (cluster_index * CLUSTER_SPAN) +407 (proc_index * ICU_SPAN);408 409 *buffer = icu_address[register_index]; // read word410 return 0;411 412 #endif413 406 } 414 407 … … 763 756 else 764 757 { 765 unsigned char *fb_address = (unsigned char*)&seg_fb _base + offset;758 unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset; 766 759 memcpy((void*)fb_address, (void*)buffer, length); 767 760 return 0; … … 789 782 else 790 783 { 791 unsigned char *fb_address = (unsigned char*)&seg_fb _base + offset;784 unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset; 792 785 memcpy((void*)buffer, (void*)fb_address, length); 793 786 return 0; … … 833 826 if ( (user_vaddr & 0x3) || (length & 0x3) ) 834 827 { 828 _get_lock(&_tty_put_lock); 835 829 _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n"); 830 _release_lock(&_tty_put_lock); 836 831 return 1; 837 832 } … … 841 836 842 837 // compute frame buffer pbase address 843 unsigned int fb_vaddr = (unsigned int)&seg_fb _base + offset;838 unsigned int fb_vaddr = (unsigned int)&seg_fbf_base + offset; 844 839 845 840 ko = _v2p_translate( (page_table_t*)user_ptab, … … 851 846 if ( ko ) 852 847 { 848 _get_lock(&_tty_put_lock); 853 849 _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n"); 850 _release_lock(&_tty_put_lock); 854 851 return 2; 855 852 } … … 864 861 if ( ko ) 865 862 { 863 _get_lock(&_tty_put_lock); 866 864 _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n"); 865 _release_lock(&_tty_put_lock); 867 866 return 3; 868 867 } 869 868 if ( (flags & PTE_U) == 0 ) 870 869 { 870 _get_lock(&_tty_put_lock); 871 871 _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n"); 872 _release_lock(&_tty_put_lock); 872 873 return 4; 873 874 } 874 875 if ( ( (flags & PTE_W) == 0 ) && to_user ) 875 876 { 877 _get_lock(&_tty_put_lock); 876 878 _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n"); 879 _release_lock(&_tty_put_lock); 877 880 return 5; 878 881 }
Note: See TracChangeset
for help on using the changeset viewer.