Changeset 3 for trunk/kernel/devices/dev_txt.c
- Timestamp:
- Apr 26, 2017, 2:08:13 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/devices/dev_txt.c
r1 r3 35 35 ///////////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern devices_directory_t devices_dir; // allocated in kernel_init.c37 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 38 38 39 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 40 40 41 ////////////////////////////////// 42 void dev_txt_init( xptr_t dev_xp)41 //////////////////////////////////// 42 void dev_txt_init( chdev_t * chdev ) 43 43 { 44 // get device descriptor cluster and local pointer 45 cxy_t dev_cxy = GET_CXY( dev_xp ); 46 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 44 // the local ICU chdev must be initialized before the TXT chdev, because 45 // the TXT chdev initialisation requires allocation of a WTI from local ICU 46 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 47 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before TXT" ); 47 48 48 // get implementation index from device descriptor 49 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 49 // get implementation and channel index 50 uint32_t impl = chdev->impl; 51 uint32_t channel = chdev->channel; 50 52 51 // get channel index from device descriptor 52 // uint32_t channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) ); 53 54 // set fields "cmd", "isr", and "name" in device descriptor 55 // and call implementation specific init function 56 57 // TODO replace fixed "TXT_TTY" name by a channel indexed "TXT_TTY%d" name 58 // as soon as the sprintk() function is available 59 53 // set fields "cmd", "isr", and call driver init function 60 54 if( impl == IMPL_TXT_TTY ) 61 55 { 62 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_tty_command ); 63 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_tty_isr ); 64 // sprintk( name , "TXT_TTY%d" , channel ) 65 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 66 XPTR( local_cxy , "TXT_TTY" ) , 16 ); 67 soclib_tty_init( dev_xp ); 56 chdev->cmd = &soclib_tty_cmd; 57 chdev->isr = &soclib_tty_isr; 58 soclib_tty_init( chdev ); 68 59 } 69 60 else 70 61 { 71 printk("\n[PANIC] in %s: undefined TXT device implementation\n", __FUNCTION__ ); 72 hal_core_sleep(); 62 assert( false , __FUNCTION__ , "undefined TXT device implementation" ); 73 63 } 74 64 65 // get a WTI mailbox from local ICU 66 uint32_t wti_id = dev_icu_wti_alloc(); 67 68 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 69 70 // select a core 71 lid_t lid = cluster_select_local_core(); 72 73 // enable WTI IRQ and update WTI interrupt vector 74 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 75 76 // link IOC IRQ to WTI mailbox in PIC component 77 uint32_t irq_id = chdev_pic_input.txt[channel]; 78 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 79 75 80 // create server thread 76 xptr_t new_thread_xp; 77 thread_t * new_thread_ptr; 81 thread_t * new_thread; 78 82 error_t error; 79 83 80 if( dev_cxy == local_cxy ) // device cluster is local 81 { 82 error = thread_kernel_create( &new_thread_ptr, 83 THREAD_DEV, 84 &dev_txt_server, 85 dev_ptr, 86 cluster_select_local_core() ); 87 88 new_thread_xp = XPTR( local_cxy , new_thread_ptr ); 89 } 90 else // device cluster is remote 91 { 92 rpc_thread_kernel_create_client( dev_cxy, 93 THREAD_DEV, 94 &dev_txt_server, 95 dev_ptr, 96 &new_thread_xp, 97 &error ); 84 error = thread_kernel_create( &new_thread, 85 THREAD_DEV, 86 &chdev_sequencial_server, 87 chdev, 88 lid ); 89 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 98 90 99 new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp ); 100 } 101 if( error ) 102 { 103 printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ ); 104 hal_core_sleep(); 105 } 106 107 // initialises server field in device descriptor 108 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr ); 91 // set "server" field in chdev descriptor 92 chdev->server = new_thread; 109 93 110 94 // start server thread 111 thread_unblock( new_thread_xp, THREAD_BLOCKED_GLOBAL );95 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 112 96 113 97 } // end dev_txt_init() … … 115 99 116 100 ////////////////////////////////////////////////////////////////////////////////// 117 // This static function is called by dev_txt_read(), dev_txt_write(), and 118 // dev_txt_sync_write() functions. 119 // For the TXT_READ and TXT_WRITE operation types: 120 // - it build the command, and registers it in the calling thread descriptor. 121 // - then, it registers the calling thead in device waiting queue. 122 // - finally, it blocks on the THREAD_BLOCKED_DEV condition and deschedule. 123 // For the TXT_SYNC_WRITE operation type: 124 // - it directly call the relevant driver, using a busy waiting policy. 101 // This static function is called by dev_txt_read(), dev_txt_write() functions. 125 102 ////////////////////////////////////i///////////////////////////////////////////// 126 103 static error_t dev_txt_access( uint32_t type, … … 135 112 136 113 // check channel argument 137 if( channel >= CONFIG_MAX_TXT_CHANNELS ) 138 { 139 printk("\n[PANIC] in %s : illegal channel index = %d\n", __FUNCTION__ , channel ); 140 hal_core_sleep(); 141 } 114 assert( (channel < CONFIG_MAX_TXT_CHANNELS) , __FUNCTION__ , "illegal channel index" ); 142 115 143 // get extended pointer on remote TXT devicedescriptor144 xptr_t dev_xp = devices_dir.txt[channel];116 // get extended pointer on remote TXT chdev descriptor 117 xptr_t dev_xp = chdev_dir.txt[channel]; 145 118 146 if ( dev_xp == XPTR_NULL ) 147 { 148 printk("\n[PANIC] in %s : undefined TXT device descriptor for channel %d\n", 149 __FUNCTION__ , channel ); 150 hal_core_sleep(); 151 } 119 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT chdev descriptor" ); 152 120 153 121 // register command in calling thread descriptor 154 this-> dev.txt.dev_xp = dev_xp;155 this-> dev.txt.type = type;156 this-> dev.txt.buf_xp = XPTR( local_cxy , buffer );157 this-> dev.txt.count = count;122 this->command.txt.dev_xp = dev_xp; 123 this->command.txt.type = type; 124 this->command.txt.buf_xp = XPTR( local_cxy , buffer ); 125 this->command.txt.count = count; 158 126 127 // register client thread in waiting queue, activate server thread 128 // block client thread on THREAD_BLOCKED_IO and deschedule. 129 // it is re-activated by the ISR signaling IO operation completion. 130 chdev_register_command( dev_xp , this ); 159 131 160 if( (type == TXT_READ) || (type == TXT_WRITE) ) // descheduling policy 161 { 162 // get a free WTI mailbox 163 uint32_t wti_id; 164 while( 1 ) 165 { 166 wti_id = dev_icu_wti_alloc(); 167 if( wti_id == -1 ) sched_yield(); 168 else break; 169 } 170 171 // enable WTI IRQ in local ICU and update WTI interrupt vector 172 dev_icu_enable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp ); 173 174 // link TXT IRQ to WTI mailbox in PIC component 175 uint32_t irq_id = devices_input_irq.txt[channel]; 176 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 177 178 // register client thread in waiting queue, activate server thread 179 // block client thread on THREAD_BLOCKED_IO and deschedule. 180 // it is re-activated by the ISR signaling IO operation completion. 181 device_register_command( dev_xp , this ); 182 183 // access PIC to unlink the IOC IRQ 184 dev_pic_unbind_irq( irq_id ); 185 186 // disable WTI IRQ in ICU and update interrupt vector 187 dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id ); 188 189 // release WTI mailbox 190 dev_icu_wti_release( wti_id ); 191 192 txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 193 __FUNCTION__ , this->trdid , this->process->pid , this->dev.txt.error ); 194 } 195 else if( type == TXT_SYNC_WRITE ) // busy waiting policy 196 { 197 // get driver command function pointer from remote TXT device descriptor 198 cxy_t dev_cxy = GET_CXY( dev_xp ); 199 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 200 dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) ); 201 202 // take the TXT device lock, because the calling thread does NOT 203 // register in device waiting queue for this synchronous command, 204 // and has exclusive access to the terminal... 205 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 206 207 // call directly driver command 208 cmd( XPTR( local_cxy , this ) ); 209 210 // release the TXT device lock 211 remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 212 } 132 txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 133 __FUNCTION__ , this->trdid , this->process->pid , this->command.txt.error ); 213 134 214 135 // return I/O operation status from calling thread descriptor 215 return this-> dev.txt.error;136 return this->command.txt.error; 216 137 217 138 } // end dev_txt_access() … … 225 146 } 226 147 227 ///////////////////////////////////////////////228 error_t dev_txt_sync_write( uint32_t channel,229 char * buffer,230 uint32_t count )231 {232 return dev_txt_access( TXT_SYNC_WRITE , channel , buffer , count );233 }234 235 148 ///////////////////////////////////////// 236 149 error_t dev_txt_read( uint32_t channel, … … 240 153 } 241 154 242 ///////////////////////////////////// 243 void dev_txt_server( device_t * dev ) 155 /////////////////////////////////////////////// 156 error_t dev_txt_sync_write( uint32_t channel, 157 char * buffer, 158 uint32_t count ) 244 159 { 245 xptr_t client_xp; // extended pointer on waiting thread 246 cxy_t client_cxy; // cluster of client thread 247 thread_t * client_ptr; // local pointer on client thread 248 thread_t * server; // local pointer on server thread 249 xptr_t root_xp; // extended pointer on device waiting queue root 160 // get pointer on calling thread 161 thread_t * this = CURRENT_THREAD; 250 162 251 server = CURRENT_THREAD; 163 // get extended pointer on TXT[0] chdev 164 xptr_t dev_xp = chdev_dir.txt[channel]; 252 165 253 root_xp = XPTR( local_cxy , &dev->wait_root ); 166 // register command in calling thread 167 this->command.txt.dev_xp = dev_xp; 168 this->command.txt.type = TXT_SYNC_WRITE; 169 this->command.txt.buf_xp = XPTR( local_cxy , buffer ); 170 this->command.txt.count = count; 254 171 255 // infinite loop handling commands of threads 256 // registered in the TXT waiting queue 257 while( 1 ) 258 { 259 // get lock protecting queue 260 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) ); 172 // get driver command function 173 cxy_t dev_cxy = GET_CXY( dev_xp ); 174 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 175 dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) ); 261 176 262 // block and deschedule server thread if waiting queue empty 263 if( xlist_is_empty( root_xp ) ) 264 { 265 thread_block( server , THREAD_BLOCKED_DEV_QUEUE ); 266 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 267 sched_yield(); 268 } 269 else 270 { 271 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 272 } 177 // call directly driver command after taking chdev lock 178 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 179 cmd( XPTR( local_cxy , this ) ); 180 remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 273 181 274 // get extended pointer on first client thread 275 client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 182 // return I/O operation status from calling thread descriptor 183 return this->command.txt.error; 184 185 } // end dev_txt_sync_write() 276 186 277 // call driver command function to start I/O operation278 dev->cmd( client_xp );279 280 // get client thread cluster and local pointer281 client_cxy = GET_CXY( client_xp );282 client_ptr = (thread_t *)GET_PTR( client_xp );283 284 // remove the client thread from waiting queue285 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );286 xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );287 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );288 289 } // end while290 291 } // end dev_txt_server()292
Note: See TracChangeset
for help on using the changeset viewer.