source: trunk/kernel/kern/chdev.c @ 388

Last change on this file since 388 was 317, checked in by alain, 7 years ago

1) Introduce the TSAR hal_cpu_context_switch() function.
2) Introduce the generic vfs_kernel_move() function.

File size: 9.0 KB
RevLine 
[5]1/*
2 * chdev.c - channel device descriptor operations implementation.
3 *
4 * Authors  Alain Greiner   (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[14]24#include <kernel_config.h>
[5]25#include <hal_types.h>
26#include <hal_special.h>
[16]27#include <printk.h>
[5]28#include <boot_info.h>
29#include <xlist.h>
30#include <kmem.h>
31#include <thread.h>
32#include <rpc.h>
33#include <chdev.h>
[23]34#include <devfs.h>
[5]35
[317]36
37extern chdev_directory_t    chdev_dir;   // allocated in kernel_init.c
38
39
[5]40////////////////////////////////////////////
41char * chdev_func_str( uint32_t func_type ) 
42{
43        if     ( func_type == DEV_FUNC_RAM ) return "RAM";
44        else if( func_type == DEV_FUNC_ROM ) return "ROM";
45        else if( func_type == DEV_FUNC_FBF ) return "FBF";
46        else if( func_type == DEV_FUNC_IOB ) return "IOB";
47        else if( func_type == DEV_FUNC_IOC ) return "IOC";
48        else if( func_type == DEV_FUNC_MMC ) return "MMC";
49        else if( func_type == DEV_FUNC_DMA ) return "DMA";
50        else if( func_type == DEV_FUNC_NIC ) return "NIC";
51        else if( func_type == DEV_FUNC_TIM ) return "TIM";
52        else if( func_type == DEV_FUNC_TXT ) return "TXT";
53        else if( func_type == DEV_FUNC_ICU ) return "ICU";
54        else if( func_type == DEV_FUNC_PIC ) return "PIC";
[16]55    else                                 return "undefined";
[5]56}
57
58/////////////////////////////////////////
59chdev_t * chdev_create( uint32_t    func,
60                        uint32_t    impl,
61                        uint32_t    channel,
62                        uint32_t    is_rx,
63                        xptr_t      base )
64{
65    chdev_t    * chdev;
66    kmem_req_t   req;
67
68    // allocate memory for chdev
69    req.type   = KMEM_DEVICE;
70    req.flags  = AF_ZERO;
71    chdev      = (chdev_t *)kmem_alloc( &req );
72
73    if( chdev == NULL ) return NULL;
74
75    // initialize waiting threads queue and associated lock
76    remote_spinlock_init( XPTR( local_cxy , &chdev->wait_lock ) );
77    xlist_root_init( XPTR( local_cxy , &chdev->wait_root ) );
78
79    // initialize attributes
80    chdev->func    =  func;
81    chdev->impl    =  impl;
82    chdev->channel =  channel;
83    chdev->is_rx   =  is_rx;
84    chdev->base    =  base; 
85
86    return chdev;
87
88}  // end chdev_create()
89
90///////////////////////////////////
91void chdev_print( chdev_t * chdev )
92{
93    printk("\n - func      = %s"
94           "\n - channel   = %d"
95           "\n - base      = %l"
96           "\n - cmd       = %x"
97           "\n - isr       = %x"
98           "\n - chdev     = %x\n",
99           chdev_func_str(chdev->func),
100           chdev->channel,
101           chdev->base,
102           chdev->cmd,
103           chdev->isr,
104           chdev );
105}
106
107////////////////////////////////////////////////
108void chdev_register_command( xptr_t     chdev_xp,
109                             thread_t * thread )
110{
111    thread_t * thread_ptr = CURRENT_THREAD;
112
113    // get device descriptor cluster and local pointer
114    cxy_t     chdev_cxy = GET_CXY( chdev_xp );
115    chdev_t * chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
116
117    // build extended pointers on client thread xlist and device root
118    xptr_t  xp_list = XPTR( local_cxy , &thread_ptr->wait_list );
119    xptr_t  xp_root = XPTR( chdev_cxy , &chdev_ptr->wait_root );
120
121    // get lock protecting queue
122    remote_spinlock_lock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
123
124    // register client thread in waiting queue
125    xlist_add_last( xp_root , xp_list );
126
127    // unblock server thread
128    thread_unblock( XPTR( chdev_cxy , &chdev_ptr->server ) , THREAD_BLOCKED_DEV_QUEUE );
129
130    // release lock
131    remote_spinlock_unlock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
132
133    // client thread goes to blocked state and deschedule
134    thread_block( thread_ptr , THREAD_BLOCKED_IO );
[296]135    sched_yield( NULL );
[5]136
137}  // end chdev_register_command()
138
139///////////////////////////////////////////////
140void chdev_sequencial_server( chdev_t * chdev )
141{
142    xptr_t          client_xp;    // extended pointer on waiting thread
143    cxy_t           client_cxy;   // cluster of client thread
144    thread_t      * client_ptr;   // local pointer on client thread
145    thread_t      * server;       // local pointer on this thread
146    xptr_t          root_xp;      // extended pointer on device waiting queue root
147
148    server = CURRENT_THREAD;
149
150    root_xp = XPTR( local_cxy , &chdev->wait_root );
151
152    // take the lock protecting the chdev waiting queue, before entering the
153        // infinite loop handling commands registered in this queue.
154    // In the loop, the lock is released during the handling of one command.
155
156    remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
157
158    while( 1 )
159    {
160        // check waiting queue state
161        if( xlist_is_empty( root_xp ) ) // block and deschedule if waiting queue empty
162        {
163            // release lock
164            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
165
166            // block and deschedule
167            thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
[296]168            sched_yield( NULL );
[5]169        } 
170        else
171        {
172            // release lock
173            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
174        }
175
176        // get extended pointer on first client thread
177        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
178
179        // call driver command function to execute I/O operation
180        chdev->cmd( client_xp );
181       
182        // get client thread cluster and local pointer
183        client_cxy = GET_CXY( client_xp );
184        client_ptr = (thread_t *)GET_PTR( client_xp );
185
186        // take the lock, and remove the client thread from waiting queue
187        remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
188        xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
189
190    }  // end while
191
192}  // end chdev_sequencial_server()
193
[317]194////////////////////////
195void chdev_dir_display()
196{
197    cxy_t     iob_cxy  = GET_CXY( chdev_dir.iob );
198    chdev_t * iob_ptr  = (chdev_t *)GET_PTR( chdev_dir.iob );
199    xptr_t    iob_base = hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) );
200
201    cxy_t     pic_cxy  = GET_CXY( chdev_dir.pic );
202    chdev_t * pic_ptr  = (chdev_t *)GET_PTR( chdev_dir.pic );
203    xptr_t    pic_base = hal_remote_lwd( XPTR( pic_cxy , &pic_ptr->base ) );
204
205    cxy_t     txt0_cxy  = GET_CXY( chdev_dir.txt[0] );
206    chdev_t * txt0_ptr  = (chdev_t *)GET_PTR( chdev_dir.txt[0] );
207    xptr_t    txt0_base = hal_remote_lwd( XPTR( txt0_cxy , &txt0_ptr->base ) );
208
209    cxy_t     txt1_cxy  = GET_CXY( chdev_dir.txt[1] );
210    chdev_t * txt1_ptr  = (chdev_t *)GET_PTR( chdev_dir.txt[1] );
211    xptr_t    txt1_base = hal_remote_lwd( XPTR( txt1_cxy , &txt1_ptr->base ) );
212
213    cxy_t     txt2_cxy  = GET_CXY( chdev_dir.txt[2] );
214    chdev_t * txt2_ptr  = (chdev_t *)GET_PTR( chdev_dir.txt[2] );
215    xptr_t    txt2_base = hal_remote_lwd( XPTR( txt2_cxy , &txt2_ptr->base ) );
216
217    cxy_t     ioc_cxy  = GET_CXY( chdev_dir.ioc[0] );
218    chdev_t * ioc_ptr  = (chdev_t *)GET_PTR( chdev_dir.ioc[0] );
219    xptr_t    ioc_base = hal_remote_lwd( XPTR( ioc_cxy , &ioc_ptr->base ) );
220
221    cxy_t     fbf_cxy  = GET_CXY( chdev_dir.fbf[0] );
222    chdev_t * fbf_ptr  = (chdev_t *)GET_PTR( chdev_dir.fbf[0] );
223    xptr_t    fbf_base = hal_remote_lwd( XPTR( fbf_cxy , &fbf_ptr->base ) );
224
225    cxy_t     nic_rx_cxy  = GET_CXY( chdev_dir.nic_rx[0] );
226    chdev_t * nic_rx_ptr  = (chdev_t *)GET_PTR( chdev_dir.nic_rx[0] );
227    xptr_t    nic_rx_base = hal_remote_lwd( XPTR( nic_rx_cxy , &nic_rx_ptr->base ) );
228
229    cxy_t     nic_tx_cxy  = GET_CXY( chdev_dir.nic_tx[0] );
230    chdev_t * nic_tx_ptr  = (chdev_t *)GET_PTR( chdev_dir.nic_tx[0] );
231    xptr_t    nic_tx_base = hal_remote_lwd( XPTR( nic_tx_cxy , &nic_tx_ptr->base ) );
232
233    printk("\n***** external chdev directory in cluster %x\n"
234           "  - iob       = %l / base = %l\n"
235           "  - pic       = %l / base = %l\n"
236           "  - txt[0]    = %l / base = %l\n"
237           "  - txt[1]    = %l / base = %l\n"
238           "  - txt[2]    = %l / base = %l\n"
239           "  - ioc[0]    = %l / base = %l\n"
240           "  - fbf[0]    = %l / base = %l\n"
241           "  - nic_rx[0] = %l / base = %l\n"
242           "  - nic_tx[0] = %l / base = %l\n",
243           local_cxy,
244           chdev_dir.iob, iob_base,
245           chdev_dir.pic, pic_base,
246           chdev_dir.txt[0], txt0_base,
247           chdev_dir.txt[1], txt1_base,
248           chdev_dir.txt[2], txt2_base,
249           chdev_dir.ioc[0], ioc_base,
250           chdev_dir.fbf[0], fbf_base,
251           chdev_dir.nic_rx[0], nic_rx_base,
252           chdev_dir.nic_tx[0], nic_tx_base );
253
254}  // end chdev_dir_display()
255
Note: See TracBrowser for help on using the repository browser.